(*======================================================================*)
(*  Interface between LibV OS - abstraction layer and Delphi.           *)
(*  Copyright (C) 1998-2002 Vladimir A. Smirnov.                        *)
(*  Last update: 27.11.2002 (still need to be corrected)                *)
(*======================================================================*)

unit
  LibV;

interface

uses
  Windows, Math, OpenGL, SysUtils;

(*
 * The defines below must be the same as in ../include/v_config.h
{$DEFINE CONFIG_DOUBLEVEC}
 *)

{$DEFINE CHECKED_BUILD}
{$DEFINE VECTOR_EXTRA_GET_SET}
{$DEFINE MATRIX_EXTRA_GET_SET}
{$DEFINE CONFIG_WIN32_DIBOBJECT}
{$DEFINE CONFIG_GL_PRECOMPILED_FONT}

{$DEFINE MSC} { Assume DLL compiled with Microsoft Visual C }

const
  V_LIB_DLL   = 'libv.dll'; { DLL name }

(*======================================================================*)
(*  v_types.h                                                           *)

const
  BOGUS_LIMIT                         = 1024*1024-1;
  MAXCHAR                             = $7F;
  MINCHAR                             = $80;
  MAXSHORT                            = $7FFF;
  MINSHORT                            = $8000;
  MAXLONG                             = $7FFFFFFF;
  MINLONG                             = $80000000;
  MAXFLOAT                            = 3.4e+38;
  MAXDOUBLE                           = 1.7e+308;
  FLOAT_ZERO_EPSILON                  = 1e-6;
  FLOAT_ZERO_EPSILON_SQUARE           = 1e-12;

{$IFDEF CONFIG_DOUBLEVEC}
  MAXVEC                              = MAXFLOAT;
{$ELSE}     { CONFIG_DOUBLEVEC }
  MAXVEC                              = MAXDOUBLE;
{$ENDIF}    { CONFIG_DOUBLEVEC }

const
  LIBV_INVALID_HANDLE                 = nil;

type
  vhandle_t                           = pointer;
  u8_t                                = Byte;
  s8_t                                = ShortInt;
  u16_t                               = Word;
  s16_t                               = SmallInt;
  u32_t                               = LongInt;
  s32_t                               = Integer;
  u_64                                = Comp;
  s_64                                = Comp;
  vboolean                            = LongBool;
  void_p                              = Pointer;
  char_p                              = PChar;
  u16_p                               = ^u16_t;
  u32_p                               = ^u32_t;
{$IFDEF CONFIG_DOUBLEVEC}
  vec_t                               = double;
{$ELSE}
  vec_t                               = single;
{$ENDIF}
  vec_p                               = ^vec_t;

  vec2_t                              = array[0..1] of vec_t;
  vec2_p                              = ^vec2_t;
  vec3_t                              = array[0..2] of vec_t;
  vec3_p                              = ^vec3_t;
  vec4_t                              = array[0..3] of vec_t;
  vec4_p                              = ^vec4_t;
  rgb_t                               = vec_t;
  rgba_t                              = vec4_t;
  color3b_t                           = array[0..2] of byte;
  color3b_p                           = ^color3b_t;
  _color3b_t_array_t                  = array[0..BOGUS_LIMIT]
                      of color3b_t;
  color3b_t_array_p                   = ^_color3b_t_array_t;
  color4b_t                           = array[0..3] of byte;
  color4b_p                           = ^color4b_t;
  _color4b_t_array_t                  = array[0..BOGUS_LIMIT]
                      of color4b_t;
  color4b_t_array_p                   = ^_color4b_t_array_t;
  matrix2_t                           = array[0..1,0..1] of vec_t;
  matrix2_p                           = ^matrix2_t;
  matrix3_t                           = array[0..2,0..2] of vec_t;
  matrix3_p                           = ^matrix3_t;
  matrix4_t                           = array[0..3,0..3] of vec_t;
  matrix4_p                           = ^matrix4_t;
  matrix3x4_t                         = array[0..2,0..3] of vec_t;
  matrix3x4_p                         = ^matrix3x4_t;

  (*  Arrays: there is no clear way to define them in ObjectPascal.   *)

  _void_p_array_t                     = array[0..BOGUS_LIMIT] of void_p;
  void_p_array_p                      = ^_void_p_array_t;
  
  _s32_t_array_t                      = array[0..BOGUS_LIMIT] of s32_t;
  s32_t_array_p                       = ^_s32_t_array_t;
  _s32_t_array_p_array_t              = array[0..BOGUS_LIMIT]
                      of s32_t_array_p;
  s32_t_array_p_array_p               = ^_s32_t_array_p_array_t;

  _u32_t_array_t                      = array[0..BOGUS_LIMIT] of u32_t;
  u32_t_array_p                       = ^_u32_t_array_t;

  _u8_t_array_t                       = array[0..BOGUS_LIMIT] of u8_t;
  u8_t_array_p                        = ^_u8_t_array_t;

  _vec_t_array_t                      = array[0..BOGUS_LIMIT] of vec_t;
  vec_t_array_p                       = ^_vec_t_array_t;
  _vec_t_array_p_array_t               = array[0..BOGUS_LIMIT]
    of vec_t_array_p;
  vec_t_array_p_array_p               = ^_vec_t_array_p_array_t;

  _vec2_t_array_t                     = array[0..BOGUS_LIMIT] of vec2_t;
  vec2_t_array_p                      = ^_vec2_t_array_t;
  _vec3_t_array_t                     = array[0..BOGUS_LIMIT] of vec3_t;
  vec3_t_array_p                      = ^_vec3_t_array_t;
  _vec4_t_array_t                     = array[0..BOGUS_LIMIT] of vec4_t;
  vec4_t_array_p                      = ^_vec4_t_array_t;

(*======================================================================*)
(* v_lib.h                                                              *)
function    memAlloc(size:u32_t):pointer;stdcall;external V_LIB_DLL;
function    memIsPointer(blk:pointer):vboolean;stdcall;external V_LIB_DLL;
function    memRealloc(blk:pointer;newsize:u32_t):pointer;
  stdcall;external V_LIB_DLL;
procedure   memFree(block:pointer);stdcall;external V_LIB_DLL;

procedure   memPrintStats;stdcall;external V_LIB_DLL;
(*
 * Returns either NT version (4 for WinNT,5 for Win2k/XP) or -1 (MustDie)
 *)
function    ntGetVersion:integer;stdcall;external V_LIB_DLL;
(*  =================================================================== *)
(*  sched.h                                                             *)
type
  thread_proc_t   = procedure(param:pointer);stdcall;
  thread_t        = vhandle_t;
  mutex_t         = vhandle_t;
  cond_t          = vhandle_t;
function    threadCreate(start_address:thread_proc_t;
  arg:pointer):thread_t;stdcall;external V_LIB_DLL;
function    threadJoin(thread:thread_t;pexit_code:u32_p):vboolean;
  stdcall;external V_LIB_DLL;
procedure   threadExit(exit_code:u32_t);stdcall;external V_LIB_DLL;
function    threadLive(thread:thread_t):vboolean;
  stdcall;external V_LIB_DLL;
function    mutexCreate:mutex_t;stdcall;external V_LIB_DLL;
procedure   mutexLock(mutex:mutex_t);stdcall;external V_LIB_DLL;
function    mutexTryLock(mutex:mutex_t):vboolean;
  stdcall;external V_LIB_DLL;
procedure   mutexUnlock(mutex:mutex_t);stdcall;external V_LIB_DLL;
procedure   mutexDestroy(mutex:mutex_t);stdcall;external V_LIB_DLL;
function    condCreate(autoreset:vboolean):cond_t;
  stdcall;external V_LIB_DLL;
function    condSet(cond:cond_t):vboolean;stdcall;external V_LIB_DLL;
function    condReset(cond:cond_t):vboolean;stdcall;external V_LIB_DLL;
function    condPulse(cond:cond_t):vboolean;stdcall;external V_LIB_DLL;
function    condWait(cond:cond_t):vboolean;stdcall;external V_LIB_DLL;
function    condTimedWait(cond:cond_t;milliseconds:u32_t):vboolean;
  stdcall;external V_LIB_DLL;
procedure   condDestroy(cond:cond_t);stdcall;external V_LIB_DLL;
(*  =================================================================== *)
(*  x86.h                                                               *)
{$IFDEF MSC}

{$IFDEF CONFIG_DOUBLEVEC}
procedure v_fsincos(var s,c:vec_t;r:vec_t);
  stdcall;external V_LIB_DLL name 'v_fsincos_d';
{$ELSE}     { CONFIG_DOUBLEVEC }
procedure v_fsincos(var s,c:vec_t;r:vec_t);
  stdcall;external V_LIB_DLL name 'v_fsincos_f';
{$ENDIF} { CONFIG_DOUBLEVEC }

procedure memFill(dst:void_p;value:u32_t;count:s32_t);
  stdcall;external V_LIB_DLL;
procedure memFill32(dst:void_p;value:u32_t;dwords:s32_t);
  stdcall;external V_LIB_DLL;
procedure memZero(dst:void_p;count:s32_t);
  stdcall;external V_LIB_DLL;
procedure memZero32(dst:void_p;dwords:s32_t);
  stdcall;external V_LIB_DLL;
procedure memCopy(dst,src:void_p;count:s32_t);
  stdcall;external V_LIB_DLL;
procedure memCopy32(dst,src:void_p;dwords:s32_t);
  stdcall;external V_LIB_DLL;

{$ELSE}   { MSC }

procedure v_fsincos(var s,c:vec_t;r:vec_t);
procedure memFill(dst:void_p;value:u32_t;count:s32_t);
procedure memFill32(dst:void_p;value:u32_t;dwords:s32_t);
procedure memZero(dst:void_p;count:s32_t);
procedure memZero32(dst:void_p;dwords:s32_t);
procedure memCopy(dst,src:void_p;count:s32_t);
procedure memCopy32(dst,src:void_p;dwords:s32_t);

{$ENDIF}  { MSC }

(*  =================================================================== *)
(*  05.02.2003															*)

(*
 * Forward and inverse FFT
 *
 * If dir_sign == 1:
 * Input:
 * ReIn - array[0..2^size_power] of vec_t; - real part of signal in time domain
 * ImIn - array[0..2^size_power] of vec_t; - imaginary part of signal in time domain
 *
 * Output:
 * ReOut - array[0..2^size_power] of vec_t; - real part of signal in freq domain
 * ImOut - array[0..2^size_power] of vec_t; - imaginary part of signal in freq domain
 *
 * If dir_sign == -1:
 * Input:
 * ReIn - array[0..2^size_power] of vec_t; - real part of signal in freq domain
 * ImIn - array[0..2^size_power] of vec_t; - imaginary part of signal in freq domain
 *
 * Output:
 * ReOut - array[0..2^size_power] of vec_t; - real part of signal in time domain
 * ImOut - array[0..2^size_power] of vec_t; - imaginary part of signal in time domain
 *)
 
procedure	fftCalcNip(ReOut,ImOut,ReIn,ImIn:vec_t_array_p;
	size_power:u32_t;dir_sign:vec_t);stdcall;external V_LIB_DLL;

(*  =================================================================== *)
(*  v_math.h                                                            *)
const
  M_PI                                = 3.1415926535898;
  M_2PI                               = 6.2831853071796;
  M_PI2                               = 1.5707963267949;
  M_PI3                               = 1.0471975511966;
  M_PI4                               = 0.7853981633975;
  M_PI6                               = 0.5235987755983;
  (*  Angles in radians; after underscore - angle in degrees. *)
  ANGLE_0                             = 0.0;
  ANGLE_1                             = 0.017453292;
  ANGLE_5                             = 0.087266462;
  ANGLE_10                            = 0.174532925;
  ANGLE_15                            = 0.261799387;
  ANGLE_20                            = 0.392699081;
  ANGLE_30                            = 0.523598775;
  ANGLE_45                            = 0.785398163;
  ANGLE_60                            = 1.047197551;
  ANGLE_72                            = 1.256637061;
  ANGLE_90                            = 1.570796327;
  ANGLE_120                           = 2.094395102;
  ANGLE_135                           = 2.35619449;
  ANGLE_144                           = 2.513274123;
  ANGLE_180                           = 3.141592653;
  ANGLE_225                           = 3.926990817;
  ANGLE_270                           = 4.71238898;
  ANGLE_315                           = 5.497787144;
  ANGLE_360                           = 6.283185307;
  RAD_IN_ANGLE                        = 0.01745329251994;
  ANGLE_TO_RAD                        = 0.01745329251994;
  ANGLE_IN_RAD                        = 57.29577951618;
  RAD_TO_ANGLE                        = 57.29577951618;
  (* Indices of quat angles stored in vec3_t *)
  PITCH                               = 0;
  YAW                                 = 1;
  ROLL                                = 2;

function  ToRadians(a:vec_t):vec_t;
function  ToDegrees(a:vec_t):vec_t;
procedure vec2Set(var vec:vec2_t;x,y:vec_t);
procedure vec3Set(var vec:vec3_t;x,y,z:vec_t);
procedure vec4Set(var vec:vec4_t;x,y,z,w:vec_t);
procedure vec2Zero(var vec:vec2_t);
procedure vec3Zero(var vec:vec3_t);
procedure vec4Zero(var vec:vec4_t);
procedure vec2Copy(var dst,src:vec2_t);
procedure vec3Copy(var dst,src:vec3_t);
procedure vec4Copy(var dst,src:vec4_t);
procedure vec2Add(var dst,v1,v2:vec2_t);
procedure vec3Add(var dst,v1,v2:vec3_t);
procedure vec4Add(var dst,v1,v2:vec4_t);
procedure vec2Sub(var dst,v1,v2:vec2_t);
procedure vec3Sub(var dst,v1,v2:vec3_t);
procedure vec4Sub(var dst,v1,v2:vec4_t);
procedure vec2Scale(var dst,src:vec2_t;scale:vec_t);
procedure vec3Scale(var dst,src:vec3_t;scale:vec_t);
procedure vec4Scale(var dst,src:vec4_t;scale:vec_t);
procedure vec2Negate(var dst,src:vec2_t);
procedure vec3Negate(var dst,src:vec3_t);
procedure vec4Negate(var dst,src:vec4_t);
procedure vec2NegateSelf(var v:vec2_t);
procedure vec3NegateSelf(var v:vec3_t);
procedure vec4NegateSelf(var v:vec4_t);
function  vec2Dot(var v1,v2:vec2_t):vec_t;
function  vec3Dot(var v1,v2:vec3_t):vec_t;
function  vec4Dot(var v1,v2:vec4_t):vec_t;
function  vec2Abs(var vec:vec2_t):vec_t;
function  vec3Abs(var vec:vec3_t):vec_t;
function  vec4Abs(var vec:vec4_t):vec_t;
procedure vec2Unit(var dst,vec:vec2_t);
procedure vec3Unit(var dst,vec:vec3_t);
procedure vec4Unit(var dst,vec:vec4_t);
procedure vec4Homogenize(var dst,vec:vec4_t);
function  vec2Cross(var v1,v2:vec2_t):vec_t;
function  vec3Mix(var v1,v2,v3:vec3_t):vec_t;
function  vec2MinInd(var vec:vec2_t):integer;
function  vec2MaxInd(var vec:vec2_t):integer;
function  vec3MinInd(var vec:vec3_t):integer;
function  vec3MaxInd(var vec:vec3_t):integer;
function  vec4MinInd(var vec:vec4_t):integer;
function  vec4MaxInd(var vec:vec4_t):integer;
function  IsZero(v:vec_t):vboolean;
function  vec2IsZero(var vec:vec2_t):vboolean;
function  vec3IsZero(var vec:vec3_t):vboolean;
function  vec4IsZero(var vec:vec4_t):vboolean;
function  vec2IsEqual(var v1,v2:vec2_t):vboolean;
function  vec3IsEqual(var v1,v2:vec3_t):vboolean;
function  vec4IsEqual(var v1,v2:vec4_t):vboolean;
function  vec2IsEqualEpsilon(var a,b:vec2_t;epsilon:vec_t):vboolean;
function  vec3IsEqualEpsilon(var a,b:vec3_t;epsilon:vec_t):vboolean;
function  vec4IsEqualEpsilon(var a,b:vec4_t;epsilon:vec_t):vboolean;
procedure vec2VecScale(var dst,v1,v2:vec2_t);
procedure vec3VecScale(var dst,v1,v2:vec3_t);
procedure vec4VecScale(var dst,v1,v2:vec4_t);
procedure vec2ZoomIF(var zoom,initial,final:vec2_t);
procedure vec3ZoomIF(var zoom,initial,final:vec3_t);
procedure vec4ZoomIF(var zoom,initial,final:vec4_t);
procedure vec2ToRadians(var dst,src:vec2_t);
procedure vec3ToRadians(var dst,src:vec3_t);
procedure vec4ToRadians(var dst,src:vec4_t);
procedure vec2ToDegrees(var dst,src:vec2_t);
procedure vec3ToDegrees(var dst,src:vec3_t);
procedure vec4ToDegrees(var dst,src:vec4_t);
procedure mat2Zero(var mat:matrix2_t);
procedure mat3Zero(var mat:matrix3_t);
procedure mat4Zero(var mat:matrix4_t);
procedure mat3x4Zero(var mat:matrix3x4_t);
procedure mat2Copy(var dst,src:matrix2_t);
procedure mat3Copy(var dst,src:matrix3_t);
procedure mat4Copy(var dst,src:matrix4_t);
procedure mat3x4Copy(var dst,src:matrix3x4_t);
procedure mat2Unit(var mat:matrix2_t);
procedure mat3Unit(var mat:matrix3_t);
procedure mat4Unit(var mat:matrix4_t);
procedure mat3x4Unit(var mat:matrix3x4_t);
procedure mat2Transpose(var dst,src:matrix2_t);
procedure mat2TransposeSelf(var mat:matrix2_t);
procedure vec3Transform(var vec:vec3_t;var mat:matrix3x4_t);
(*  mat3x4ConcatBefore(): dst := transform x dst. *)
procedure mat3x4ConcatBefore(var dst,transform:matrix3x4_t);
(*  mat3x4ConcatAfter(): dst := dst x transform. *)
procedure mat3x4ConcatAfter(var dst,transform:matrix3x4_t);
procedure rgbFloatFromByte(var rgb:vec3_t;var brgb:color3b_t);
procedure rgbaFloatFromByte(var rgba:vec4_t;var brgba:color4b_t);
procedure rgbByteFromFloat(var brgb:color3b_t;var rgb:vec3_t);
procedure rgbaByteFromFloat(var brgba:color4b_t;var rgba:vec4_t);
procedure rgbFromHsv(var rgb,hsv);stdcall;external V_LIB_DLL;
procedure vec3Cross(var dst,v1,v2:vec3_t);stdcall;external V_LIB_DLL;
procedure mat4FromMat3(var mat4:matrix4_t;var mat3:matrix3_t);stdcall;
  external V_LIB_DLL;
procedure mat3FromMat4(var mat3:matrix3_t;var mat4:matrix4_t);stdcall;
  external V_LIB_DLL;
procedure mat3Transpose(var dst,src:matrix3_t);stdcall;external V_LIB_DLL;
procedure mat4Transpose(var dst,src:matrix4_t);stdcall;external V_LIB_DLL;
procedure mat2VecMul(var dst:vec2_t;var mat:matrix2_t;var v:vec2_t);stdcall;
  external V_LIB_DLL;
procedure mat3VecMul(var dst:vec3_t;var mat:matrix3_t;var v:vec3_t);stdcall;
  external V_LIB_DLL;
procedure mat3x4VecMul(var dst:vec3_t;var mat:matrix3x4_t;var v:vec3_t);
  stdcall;external V_LIB_DLL;
procedure mat4VecMul(var dst:vec4_t;var mat:matrix4_t;var v:vec4_t);
  stdcall;external V_LIB_DLL;
procedure mat2MatMul(var dst,m1,m2:matrix2_t);stdcall;external V_LIB_DLL;
procedure mat3MatMul(var dst,m1,m2:matrix3_t);stdcall;external V_LIB_DLL;
procedure mat4MatMul(var dst,m1,m2:matrix4_t);stdcall;external V_LIB_DLL;
procedure mat3x4MatMul(var dst,m1,m2:matrix3x4_t);stdcall;
  external V_LIB_DLL;
procedure vec3TransformVectors(vecs:vec3_t_array_p;var mat:matrix3x4_t;
  n:integer);stdcall;external V_LIB_DLL;
procedure mat2Solve(var a:matrix2_t;var b:vec2_t);stdcall;
  external V_LIB_DLL;
procedure mat2SolveVV(var r1,r2,b:vec2_t);stdcall;external V_LIB_DLL;
procedure mat3Solve(var a:matrix3_t;var b:vec3_t);stdcall;
  external V_LIB_DLL;
procedure mat4Solve(var a:matrix4_t;var b:vec4_t);stdcall;
  external V_LIB_DLL;

(*  =================================================================== *)
(*  u_vector.h                                                          *)
type
  vector_p        = ^vector_t;
  vector_t        = record
    size        : u32_t;
    elements    : vec_t_array_p;
  end;

(*  Returned vectors should be released via memFree *)
function    vecAlloc(size:u32_t):vector_p;
  stdcall;external V_LIB_DLL;
function    vecDuplicate(ref:vector_p):vector_p;
  stdcall;external V_LIB_DLL;
function    vecDuplicateEx(ref:vector_p;newsize:u32_t):vector_p;
  stdcall;external V_LIB_DLL;

procedure   vecAdd(dest,v1,v2:vector_p);stdcall;external V_LIB_DLL;
procedure   vecSub(dest,v1,v2:vector_p);stdcall;external V_LIB_DLL;
procedure   vecScale(dest,v:vector_p;x:vec_t);stdcall;external V_LIB_DLL;
procedure   vecNegate(v:vector_p);stdcall;external V_LIB_DLL;
function    vecCompare(v1,v2:vector_p):vboolean;stdcall;external V_LIB_DLL;
function    vecMin(v:vector_p):u32_t;stdcall;external V_LIB_DLL;
function    vecMax(v:vector_p):u32_t;stdcall;external V_LIB_DLL;

function    vecDot(v1,v2:vector_p):vec_t;
function    vecAbs(v:vector_p):vec_t;
function    vecCount(v:vector_p):u32_t;
procedure   vecCopy(dst,src:vector_p);
procedure   vecZero(v:vector_p);
procedure   vecUnit(v:vector_p);

{$IFDEF		VECTOR_EXTRA_GET_SET}
function	vecGetElement(v:vector_p;index:integer):vec_t;
procedure	vecSetElement(v:vector_p;index:integer;value:vec_t);
{$ENDIF}	{VECTOR_EXTRA_GET_SET}

(*  =================================================================== *)
(*  u_matrix.h                                                          *)
type
  matrix_p = ^matrix_t;
  matrix_t = record
    rows,cols   : u32_t;
    cell        : vec_t_array_p_array_p;
    data        : vec_t_array_p;
  end;

(*  Returned matrices should be released via memFree *)
function  matAlloc(rows,cols:u32_t):matrix_p;
  stdcall;external V_LIB_DLL;
function  matDuplicate(m:matrix_p):matrix_p;
  stdcall;external V_LIB_DLL;

procedure   matCopy(dest,src:matrix_p);stdcall;external V_LIB_DLL;
procedure   matCopyRow(dst:vector_p;m:matrix_p;row:u32_t);
  stdcall;external V_LIB_DLL;
procedure   matCopyCol(dst:vector_p;m:matrix_p;row:u32_t);
  stdcall;external V_LIB_DLL;

(*  Returned vectors should be released via memFree *)
function    matDuplicateRow(m:matrix_p;row:u32_t):vector_p;
  stdcall;external V_LIB_DLL;
function    matDuplicateCol(m:matrix_p;col:u32_t):vector_p;
  stdcall;external V_LIB_DLL;

procedure   matZero(m:matrix_p);
procedure   matUnit(m:matrix_p);stdcall;external V_LIB_DLL;
procedure   matAdd(dest,m1,m2:matrix_p);stdcall;external V_LIB_DLL;
procedure   matSub(dest,m1,m2:matrix_p);stdcall;external V_LIB_DLL;
procedure   matNegate(dest,m:matrix_p);stdcall;external V_LIB_DLL;
function    matCompare(m1,m2:matrix_p):vboolean;stdcall;external V_LIB_DLL;
procedure   matMin(m:matrix_p;var row,col:u32_t);
  stdcall;external V_LIB_DLL;
procedure   matMax(m:matrix_p;var row,col:u32_t);
  stdcall;external V_LIB_DLL;

procedure   matVecMul(dest:vector_p;m:matrix_p;v:vector_p);
  stdcall;external V_LIB_DLL;
procedure   matMatMul(dest,ml,mr:matrix_p);
  stdcall;external V_LIB_DLL;
procedure   matTranspose(destm,m:matrix_p);stdcall;external V_LIB_DLL;

(*  If !keepon, 'a' destroyed and solution placed in 'b. Otherwise
 *  both 'a' and 'b' unmodified, solution returned as result and
 *  should later be released via memFree(). *)
function    matSolve(a:matrix_p;b:vector_p;keepon:vboolean):vector_p;
  stdcall;external V_LIB_DLL;

(*  If !keepon, inversed matrix stored in 'm'. Otherwise
 *  'm' unmodified, solution returned as result and
 *  should later be released via memFree(). *)
function    matInverse(m:matrix_p;keepon:vboolean):matrix_p;
  stdcall;external V_LIB_DLL;

(*  If !keepon, 'a' destroyed; otherwise 'a' unmodified. *)
function    matDeterm(m:matrix_p;keepon:vboolean):vec_t;
  stdcall;external V_LIB_DLL;

function    matColCount(m:matrix_p):u32_t;
function    matRowCount(m:matrix_p):u32_t;

{$IFDEF		MATRIX_EXTRA_GET_SET}
function	matGetElement(m:matrix_p;irow,icol:integer):vec_t;
procedure	matSetElement(m:matrix_p;irow,icol:integer;value:vec_t);
{$ENDIF}	{MATRIX_EXTRA_GET_SET}

(*  =================================================================== *)
(*  v_plane.h                                                           *)

type
  line2_p   = ^line2_t;
  line2_t   = record
    normal  : vec2_t;
    dist    : vec_t;
  end;

  _line2_t_array_t                    = array[0..BOGUS_LIMIT] of line2_t;
  line2_t_array_p                     = ^_line2_t_array_t;

  ray2_p    = ^ray2_t;
  ray2_t    = record
    origin  : vec2_t;
    line    : line2_t;
  end;

  _ray2_t_array_t                       = array[0..BOGUS_LIMIT] of ray2_t;
  ray2_t_array_p                        = ^_ray2_t_array_t;

  poly2_p       = ^poly2_t;
  poly2_t       = record
    numpoints   : integer;
    count       : integer;
    size        : integer;
    rays        : ray2_t_array_p;
  end;

procedure mat2Rotation(var mat:matrix2_t;radians:vec_t);
procedure line2Cross(var point:vec2_t;var l1,l2:line2_t);stdcall;
  external V_LIB_DLL;
procedure line2FromPoints(var line:line2_t;var p1,p2:vec2_t);stdcall;
  external V_LIB_DLL;
function  line2DistFromPoint(var line:line2_t;var p:vec2_t):vec_t;
(*  Returns memAlloc()'ed block *)
function  poly2Alloc(points:integer):poly2_p;stdcall;external V_LIB_DLL;
(*  Returns memAlloc()'ed block *)
function  poly2Duplicate(ref:poly2_p):poly2_p;stdcall;external V_LIB_DLL;
procedure poly2ComputeEdges(w:poly2_p);stdcall;external V_LIB_DLL;
procedure poly2AddPoint(w:poly2_p;var pt:vec2_t);
function  poly2PointInside(w:poly2_p;var p:vec2_t):vboolean;stdcall;
  external V_LIB_DLL;

(*  =================================================================== *)
(*  v_space.h                                                           *)

type
  plane3_p          = ^plane3_t;
  plane3_t          = record
    normal          : vec3_t;
    dist            : vec_t;
  end;
  _plane3_t_array_t = array[0..BOGUS_LIMIT] of plane3_t;
  plane3_t_array_p  = ^_plane3_t_array_t;

  line3_p           = ^line3_t;
  line3_t           = record
    origin          : vec3_t;
    dir             : vec3_t;
  end;
  _line3_t_array_t  = array[0..BOGUS_LIMIT] of line3_t;
  line3_t_array_p   = ^_line3_t_array_t;

  vecdir_t          = integer;

const
  dir_x = 1;
  dir_y = 2;
  dir_z = 3;
  dir_anyx = 4;
  dir_anyy = 5;
  dir_anyz = 6;

procedure mat3Scale(var m:matrix3_t;var scale:vec3_t);stdcall;
  external V_LIB_DLL;
procedure mat3RotateX(var mat:matrix3_t;radians:vec_t);stdcall;
  external V_LIB_DLL;
procedure mat3RotateY(var mat:matrix3_t;radians:vec_t);stdcall;
  external V_LIB_DLL;
procedure mat3RotateZ(var mat:matrix3_t;radians:vec_t);stdcall;
  external V_LIB_DLL;
procedure mat3Rotate(var mat:matrix3_t;var dir:vec3_t;radians:vec_t);
  stdcall;external V_LIB_DLL;
procedure mat3FromDirAndUp(var mat:matrix3_t;var dir,up:vec3_t);stdcall;
  external V_LIB_DLL;

function  vec3DistFromPlane(var pt:vec3_t;pl:plane3_p):vec_t;

procedure mat3x4Scale(var mL:matrix3x4_t;var scale:vec3_t);stdcall;
  external V_LIB_DLL;
procedure mat3x4Translate(var m:matrix3x4_t;var t:vec3_t);stdcall;
  external V_LIB_DLL;
procedure mat3x4RotateX(var mat:matrix3x4_t;radians:vec_t);stdcall;
  external V_LIB_DLL;
procedure mat3x4RotateY(var mat:matrix3x4_t;radians:vec_t);stdcall;
  external V_LIB_DLL;
procedure mat3x4RotateZ(var mat:matrix3x4_t;radians:vec_t);stdcall;
  external V_LIB_DLL;
procedure mat3x4Rotate(var mat:matrix3x4_t;var dir:vec3_t;
  radians:vec_t);stdcall;external V_LIB_DLL;
procedure mat3x4FromDirAndUp(var mat:matrix3x4_t;var dir,up:vec3_t);
  stdcall;external V_LIB_DLL;
procedure mat3x4FromPointDirAndUp(var mat:matrix3x4_t;
  var pt,dir,up:vec3_t);stdcall;external V_LIB_DLL;

procedure vec3Perpendicular(var dest,v:vec3_t);stdcall;external V_LIB_DLL;
procedure vec3RotateAround(var dst,dir,point:vec3_t;radians:vec_t);
  stdcall;external V_LIB_DLL;
procedure vec3ProjectOnPlane(var proj,pt:vec3_t;plane:plane3_p);
  stdcall;external V_LIB_DLL;
procedure vec3FromLineAndPlane(var dest:vec3_t;line:line3_p;
  plane:plane3_p);stdcall;external V_LIB_DLL;
procedure vec3PlaneReflection(var dst:vec3_t;pl:plane3_p;var src:vec3_t);
  stdcall;external V_LIB_DLL;

procedure line3FromPoints(line:line3_p;var p1,p2:vec3_t);stdcall;
  external V_LIB_DLL;
procedure line3FromDirAndOrigin(line:line3_p;var dir,origin:vec3_t);
  stdcall;external V_LIB_DLL;
procedure plane3FromPoints(dest:plane3_p;var a,b,c:vec3_t);stdcall;
  external V_LIB_DLL;
procedure plane3FromLines(dest:plane3_p;l1,l2:line3_p);stdcall;
  external V_LIB_DLL;

procedure bboxClear(var mins,maxs:vec3_t);stdcall;external V_LIB_DLL;
procedure bboxAddPoint(var mins,maxs,point:vec3_t);stdcall;
  external V_LIB_DLL;
procedure bboxTransformFromBoxes(var dest:matrix3x4_t;var in_mins,
  in_maxs,out_mins,out_maxs:vec3_t);stdcall;external V_LIB_DLL;
(*  =================================================================== *)
(*  v_time.h                                                            *)
type
  timer_t = vhandle_t;

function  timeTickCount:u32_t;stdcall;external V_LIB_DLL;
procedure timeDelay(Milliseconds:u32_t);stdcall;external V_LIB_DLL;

function  timerCreate:timer_t;stdcall;external V_LIB_DLL;
procedure timerDestroy(timer:timer_t);stdcall;external V_LIB_DLL;
procedure timerStart(timer:timer_t);stdcall;external V_LIB_DLL;
procedure timerStop(timer:timer_t);stdcall;external V_LIB_DLL;
function  timerMilliseconds(timer:timer_t):u32_t;stdcall;
  external V_LIB_DLL;
procedure timerWait(timer:timer_t;ReturnTime:u32_t);stdcall;
  external V_LIB_DLL;
function  timerDiffTime(timer:timer_t):vec_t;stdcall;external V_LIB_DLL;

(*  =================================================================== *)
(*  v_image.h                                                           *)
type
  image_load_proc_t   = function(name:pchar;var w,h:integer):pointer;
    stdcall;

(*  xxxLoad() functions return memAlloc()'ed block *)
function  tgaLoad(name:pchar;var width,height:u32_t):pointer;stdcall;
  external V_LIB_DLL;
{$IFDEF CONFIG_WIN32_DIBOBJECT}
{ Creates packed DIB structure in memory }
function  bmpCreateDIBObject(pixels:void_p;width,height,
  mmWidth,mmHeight:u32_t):PBITMAPINFO;stdcall;external V_LIB_DLL;
{$ENDIF} {CONFIG_WIN32_DIBOBJECT}
procedure tgaSaveEx(name:pchar;width,height:u32_t;pixels:pointer;
  include_alpha:vboolean);stdcall;external V_LIB_DLL;
procedure tgaSave(name:pchar;width,height:u32_t;pixels:pointer);
  stdcall;external V_LIB_DLL;
function  bmpLoad(name:pchar;var width,height:u32_t):pointer;stdcall;
  external V_LIB_DLL;
procedure bmpSave(name:pchar;width,height:u32_t;pixels:pointer);
  stdcall;external V_LIB_DLL;
procedure bmpSaveEx(name:pchar;width,height:u32_t;pixels:pointer;
  mmWidth,mmHeight:u32_t);stdcall;external V_LIB_DLL;
function  bmpMMFromPixels(size,dpi:u32_t):u32_t;stdcall;
  external V_LIB_DLL;
function  jpgLoad(name:pchar;var width,height:u32_t):pointer;stdcall;
  external V_LIB_DLL;
(*  =================================================================== *)
(*  v_parse.h                                                           *)

type
  scanner_t = vhandle_t;

function  tokParseBuffer(buffer:pchar;buflen:u32_t;delim:pchar):scanner_t;
  stdcall;external V_LIB_DLL;
function  tokParseString(str,delim:pchar):scanner_t;stdcall;
  external V_LIB_DLL;
function  tokParseFile(filename,delim:pchar):scanner_t;stdcall;
  external V_LIB_DLL;
procedure tokDestroy(tok:scanner_t);stdcall;external V_LIB_DLL;
procedure tokRestart(tok:scanner_t;new_buf,new_delim:PChar);stdcall;
  external V_LIB_DLL;
function  tokPush(tok:scanner_t):s32_t;stdcall;external V_LIB_DLL;
function  tokPop(tok:scanner_t):s32_t;stdcall;external V_LIB_DLL;
(*  Returns next token or nil *)
function  tokNext(tok:scanner_t):pchar;stdcall;external V_LIB_DLL;
(*  Same as above, whitespace chars handled as normal chars *)
function  tokStrict(tok:scanner_t):pchar;stdcall;external V_LIB_DLL;
function  tokString(tok:scanner_t):pchar;stdcall;external V_LIB_DLL;
(*  Returns last result of tokNext/tokStrict/tokString *)
function  tokLast(tok:scanner_t):pchar;stdcall;external V_LIB_DLL;

(*  =================================================================== *)
(*  v_fs.h                                                              *)

type
  file_t                              = vhandle_t;

const
  SEEK_SET                            = 0;        (* from stdio.h *)
  SEEK_CUR                            = 1;
  SEEK_END                            = 2;
  _MAX_PATH                           = 255;

const
  pctl_get_name = 0;
  pctl_get_type = 1;
  pctl_duplicate_handle = 2;
  pctl_map_ispace = 3;
  pctl_get_size = 4;
  pctl_is_eof = 5;
  pctl_flush = 6;
  pctl_comm_reset = 7;
  pctl_wave_get_num_channels = 8;
  pctl_wave_get_sampling_frequency = 9;
  pctl_wave_get_bits_per_sample = 10;
  pctl_wave_get_num_samples = 11;
  pctl_wave_loop = 12;
  pctl_waveout_wait = 13;
  pctl_waveout_pause = 14;
  pctl_waveout_resume = 15;
  pctl_waveout_reset = 16;
  pctl_waveout_get_pending_samples = 17;

(*  Enumerates contents of current directory (and, optionally, all
 *  subdirectories). Currently contents of VFS NOT enumerated, but
 *  now support for transparent VFS entries enumeration can be
 *  added without great efforts.
 *  Input:
 *      - dir_callback (can be nil): caller - supplied callback
 *          for directories;
 *      - file_callback (can be nil): caller - supplied callback
 *          for files;
 *      - recursive: if nonzero, procedure enumerates all subdirs.
 *  Notes.
 *      1. dir_callback always called BEFORE directory processing;
 *  for example, if recursive = 0 than fsScan called 'dir_callback',
 *  and than, for all files in directory, 'file_callback'.
 *      2. Under MS OSes, names of files and directories passed in
 *  CYGWIN - style: "c:\winnt" becomes "//c/winnt", etc.
 *)
(*
type
  fs_callback_t   = procedure(unix_style_path:pchar);stdcall;
procedure   fsEnumFiles(dir_callback,file_callback:fs_callback_t;
  recursive:vboolean);stdcall;external V_LIB_DLL;
  name '_lfsEnumFiles@12';
*)
(* Splits full UNIX (of CYGWIN32-style) path, *)
procedure fsSplitPath(path,dir,name,ext:pchar);
  stdcall;external V_LIB_DLL;
(* Makes full UNIX (or CYGWIN32-style) path *)
procedure fsMakePath(dest,dir,name,ext:pchar);
  stdcall;external V_LIB_DLL;
(* Converts names between NT and UNIX forms *)
function  fsNative2Unix(unix_name,dos_name:PChar):vboolean;
  stdcall;external V_LIB_DLL;
function  fsUnix2Native(dos_name,unix_name:PChar):vboolean;
  stdcall;external V_LIB_DLL;
(* Replaces extension in filename *)
procedure fsReplaceExt(dst,src,ext:pchar);
  stdcall;external V_LIB_DLL;
(* Mounts all supportes VFS volumes starting from current directory *)
procedure fsInit;stdcall;external V_LIB_DLL;
(* Unmounts all mounted VFS volumes *)
procedure fsShutdown;stdcall;external V_LIB_DLL;
(*  All names in UNIX form. Invalid handle value is 0, NOT -1 ! *)
function  fileOpenRead(upath:char_p):file_t;stdcall;external V_LIB_DLL;
function  fileOpenWrite(upath:char_p):file_t;stdcall;external V_LIB_DLL;
function  fileOpenAppend(upath:char_p):file_t;
  stdcall;external V_LIB_DLL;
procedure fileClose(f:file_t);stdcall;external V_LIB_DLL;
function  fileControl(f:file_t;code:u32_t;var args):vboolean;
  stdcall;external V_LIB_DLL;

function  fileEof(f:file_t):vboolean;stdcall;external V_LIB_DLL;
function  fileSeek(f:file_t;offset,whence:integer):integer;
  stdcall;external V_LIB_DLL;
function  fileTell(f:file_t):integer;stdcall;external V_LIB_DLL;
function  fileSize(f:file_t):integer;stdcall;external V_LIB_DLL;

function  fileRead(f:file_t;buffer:pointer;size:integer):integer;
  stdcall;external V_LIB_DLL;
function  fileGetc(f:file_t):u8_t;stdcall;external V_LIB_DLL;
function  fileGets(f:file_t;buffer:pchar;maxlen:integer):integer;
  stdcall;external V_LIB_DLL;
function  fileGetLittleShort(f:file_t):u16_t;stdcall;external V_LIB_DLL;
function  fileGetLittleLong(f:file_t):u32_t;stdcall;external V_LIB_DLL;
function  fileWrite(f:file_t;buffer:pointer;size:integer):integer;
  stdcall;external V_LIB_DLL;
function  filePutc(f:file_t;ch:u8_t):vboolean;stdcall;external V_LIB_DLL;
function  filePuts(f:file_t;buffer:pchar):vboolean;
  stdcall;external V_LIB_DLL;
function  filePutLittleShort(f:file_t;val:u16_t):vboolean;
  stdcall;external V_LIB_DLL;
function  filePutLittleLong(f:file_t;val:u32_t):vboolean;
  stdcall;external V_LIB_DLL;
procedure filePrintf(f:file_t;fmt:pchar;const args:array of const);
procedure libvDosPathToUnixPath(uname,name:PChar);stdcall;external V_LIB_DLL;
procedure libvUnixPathToDosPath(name,uname:PChar);stdcall;external V_LIB_DLL;
(*  =================================================================== *)
(*  v_pgrid.h                                                           *)

type
  itriple_t           = array[0..2] of integer;
  _itriple_t_array_t  = array[0..BOGUS_LIMIT] of itriple_t;
  itriple_t_array_p   = ^_itriple_t_array_t;
  tripatch_p          = ^tripatch_t;
  tripatch_t          = record
    numvert           : integer;
    numtri            : integer;
    extinfo           : integer;
    hsplit            : integer;
    vsplit            : integer;
    base              : array[0..3] of vec3_t;
    basenormal        : vec3_t;
    vlist             : vec3_t_array_p;
    tlist             : itriple_t_array_p;
    clist             : color4b_t_array_p;
    nlist             : vec3_t_array_p;
    fnlist            : vec3_t_array_p;
    uvlist            : vec2_t_array_p;
  end;

function  patAlloc(numvert,numtri:integer;name:pchar;extinfo:integer):
  tripatch_p;stdcall;external V_LIB_DLL;
function  patDuplicate(ref:tripatch_p):tripatch_p;stdcall;
  external V_LIB_DLL;
procedure patFree(patch:tripatch_p);stdcall;external V_LIB_DLL;
procedure patDefaultGeometry(patch:tripatch_p);
  stdcall;external V_LIB_DLL;
function  patCreateRectangular(l,t,r,b:vec_t;hsplit,vsplit:integer;
  extinfo:vboolean):tripatch_p;stdcall;
  external V_LIB_DLL;
function  patCreateTriangular(var a,b,c:vec3_t;split:integer;
  extinfo:vboolean):tripatch_p;stdcall;external V_LIB_DLL;
procedure patSetGeometry(pat:tripatch_p;mat:matrix_p;ind:u32_t);
  stdcall;external V_LIB_DLL;
procedure patDrawWireframe(pat:tripatch_p);stdcall;external V_LIB_DLL;

(*  =================================================================== *)
(*  v_pprof.h: contour plots                                            *)

(*
 * Please note that this interface is obsolete and will be changes soon.
 *)

const
  BASE_XOY                            = 0;
  BASE_XOZ                            = 1;
  BASE_YOZ                            = 2;

  MAX_GRAPH_LABEL                     = 64;
  LF_NOLABEL                          = 1;
  LF_DIRECTION                        = 2;
  LF_CENTER                           = 4;

type
  graph_label_p                       = ^graph_label_t;
  graph_label_t                       = record
    dir, center                       : vec3_t;
    flags                             : integer;
    elem_size                         : vec_t;
    value                             : vec_t;
    text                              : array[0..MAX_GRAPH_LABEL-1] of char;
  end;
  _graph_label_t_array_t              = array[0..BOGUS_LIMIT] of graph_label_t;
  graph_label_t_array_p               = ^_graph_label_t_array_t;

  wirechains_p                        = ^wirechains_t;
  wirechains_t                        = record
    numvert_total                     : integer;
    numchains                         : integer;
    vlist                             : vec3_t_array_p;
    numvert                           : s32_t_array_p;
    clist                             : s32_t_array_p_array_p;
    ilist                             : s32_t_array_p;
    llist                             : graph_label_t_array_p;
  end;

  _wirechains_p_array_t               = array[0..BOGUS_LIMIT] of wirechains_p;
  wirechains_p_array_p                = ^_wirechains_p_array_t;

  planar_func_t           = function(arg1,arg2:vec_t):vec_t;stdcall;
  spatial_func_t          = function(arg1,arg2,arg3:vec_t):vec_t;stdcall;

  planar_func_p                       = ^planar_func_p;
  spatial_func_p                      = spatial_func_t;

  patchprofile_p = ^patchprofile_t;
  patchprofile_t = record
    planar       : planar_func_t;    // nil для изолиний на треугольнике
    spatial      : spatial_func_t;   // nil для обычных изолиний
    baseplane    : integer;          // 0 - xOy, 1 - xOz, 2 - yOz
    base         : array[0..3] of vec3_t;
    fmin, fmax   : vec_t;            // пределы изменения функции
    splits       : integer;          // количество серий изолиний
    wires        : wirechains_p_array_p;  // семейства изолиний.
    chainvals    : vec_t_array_p;    // значения функции на изолиниях
  end;

function  ppGridFunction(l,t,r,b:vec_t;hsplit,vsplit:integer;
  extinfo:vboolean;planar:planar_func_t;
  basenum:integer):tripatch_p;stdcall;external V_LIB_DLL;
function  ppGridSheffePolynom(center:vec3_t;radius,angle0:vec_t;
  split:integer;extinfo:vboolean;gibbs_abc:vec3_t_array_p;
  sheffe:spatial_func_t;basenum:integer):tripatch_p;stdcall;
  external V_LIB_DLL;
function  ppCreateRectangular(l,t,r,b:vec_t;func:planar_func_t;
  zsplits,baseplane:integer):patchprofile_p;stdcall;external V_LIB_DLL;
function  ppCreateTriangular(center:vec3_t;radius,angle0:vec_t;
  gibbs_abc:vec3_t_array_p;sheffe:spatial_func_t;zsplits:integer;
  baseplane:integer):patchprofile_p;stdcall;external V_LIB_DLL;
procedure ppFree(pp:patchprofile_p);stdcall;external V_LIB_DLL;

(*  =================================================================== *)
(*  v_log.h                                                             *)

const
  LOG_ANY                               = 0;
  LOG_ERROR                             = $10;
  LOG_WARNING                           = $20;
  LOG_INFO                              = $30;
  LOG_TRACE                             = $40;

type
  con_puts_t                            = procedure(str:pchar);stdcall;
  con_puts_p                            = ^con_puts_t;

function  logAddCallback(outcallback:con_puts_p):vboolean;stdcall;
  external V_LIB_DLL;
procedure logRemoveCallback(outcallback:con_puts_p);stdcall;
  external V_LIB_DLL;
procedure logUpperLevel(level:integer);stdcall;external V_LIB_DLL;
function  logStartFileLog(name:pchar;flush_every_write:vboolean):vboolean;
  stdcall;external V_LIB_DLL;
procedure logStopFileLog;stdcall;external V_LIB_DLL;
function  logStartConsoleLog:vboolean;stdcall;external V_LIB_DLL;
procedure logStopConsoleLog;stdcall;external V_LIB_DLL;
procedure conPuts(str:pchar);stdcall;external V_LIB_DLL;
procedure conlPuts(level:integer;str:pchar);stdcall;external V_LIB_DLL;
procedure conPrintf(fmt:pchar;const args:array of const);
procedure conlPrintf(level:integer;fmt:pchar;const args:array of const);

(*  =================================================================== *)
(*  v_objlib.h                                                          *)

type
  mesh_vertex_p   = ^mesh_vertex_t;
  mesh_vertex_t   = record
    vertex      : u32_t;
    texcoord    : u32_t;
    normal      : u32_t;
    color       : u32_t;
  end;
  
  mesh_face_t     = array[0..2] of mesh_vertex_t;
  _mesh_face_t_array_t    = array[0..BOGUS_LIMIT] of mesh_face_t;
  mesh_face_t_array_p     = ^_mesh_face_t_array_t;
  
  mesh_map_p      = ^mesh_map_t;
  mesh_map_t      = record
    handle      : GLuint;
    file_name   : array[0.._MAX_PATH-1] of char;
    min_filter  : GLenum;
    mag_filter  : GLenum;
    clamp_s     : GLenum;
    clamp_t     : GLenum;
  end;
  _mesh_map_t_array_t     = array[0..BOGUS_LIMIT] of mesh_map_t;
  mesh_map_t_array_p      = ^_mesh_map_t_array_t;

  mesh_mtl_p      = ^mesh_mtl_t;
  mesh_mtl_t      = record
    diffuse     : vec4_t;
    specular    : vec4_t;
    emissive    : vec4_t;
    specular_power  : vec_t;
    env             : GLenum;
    map_diffuse     : u32_t;
    map_reflection  : u32_t;
  end;
  _mesh_mtl_t_array_t     = array[0..BOGUS_LIMIT] of mesh_mtl_t;
  mesh_mtl_t_array_p      = ^_mesh_mtl_t_array_t;

  mesh_object_p   = ^mesh_object_t;
  mesh_object_t   = record
    name        : array[0..63] of char;
    material    : array[0..63] of char;
    mtlid       : u32_t;
    startface   : u32_t;
    num_faces   : u32_t;
    mins, maxs  : vec3_t;
    pivot       : vec3_t;
    xform       : matrix3x4_t;
    faces_flipped   : u32_t;
  end;
  
  _mesh_object_t_array_t  = array[0..BOGUS_LIMIT] of mesh_object_t;
  mesh_object_t_array_p   = ^_mesh_object_t_array_t;
  
  mesh_p          = ^mesh_t;
  mesh_t          = record
    num_vertices    : u32_t;
    vertex_count    : u32_t;
    num_texcoords   : u32_t;
    texcoord_count  : u32_t;
    num_normals     : u32_t;
    normal_count    : u32_t;
    num_faces       : u32_t;
    face_count      : u32_t;
    num_objects     : u32_t;
    object_count    : u32_t;
    num_colors      : u32_t;
    color_count     : u32_t;
    num_maps        : u32_t;
    map_count       : u32_t;
    num_mtls        : u32_t;
    mtl_count       : u32_t;
    minx, maxs      : vec3_t;
    vertices        : vec3_t_array_p;
    texcoords       : vec2_t_array_p;
    normals         : vec3_t_array_p;
    faces           : mesh_face_t_array_p;
    face_centers    : vec3_t_array_p;
    face_planes     : plane3_t_array_p;
    objects         : mesh_object_t_array_p;
    colors          : color4b_t_array_p;
    maps            : mesh_map_t_array_p;
    mtls            : mesh_mtl_t_array_p;
  end;
  
  _mesh_t_array_t     = array[0..BOGUS_LIMIT] of mesh_t;
  mesh_t_array_p      = ^_mesh_t_array_t;

(* Returns memAlloc()'ed block *)
function    meshAlloc(
  num_vertices,       (* number of geometry vertices *)
  num_texcoords,      (* number of texture coord vertices *)
  num_normals,        (* number of normals *)
  num_faces,          (* number of triangular faces *)
  num_objects,        (* number of objects *)
  num_colors,         (* number of color vertices *)
  num_maps,           (* number of texture maps *)
  num_mtls:u32_t      (* number of materials *)
  ):mesh_p;stdcall;external V_LIB_DLL;
(* Returns memAlloc()'ed block *)
function    objLoad(filename:pchar):mesh_p;stdcall;external V_LIB_DLL;
function    objSave(filename:pchar;obj:mesh_p):vboolean;
  stdcall;external V_LIB_DLL;

(*  =================================================================== *)
(*  v_dxf.h                                                             *)

function	dxfOpenWrite(name:pchar):file_t;stdcall;external V_LIB_DLL;
procedure	dxfLine(dxf:file_t;var p1,p2:vec3_t);stdcall;external V_LIB_DLL;
procedure	dxfQuad(dxf:file_t;var p1,p2,p3,p4:vec3_t);stdcall;external V_LIB_DLL;
procedure	dxfTriangle(dxf:file_t;var p1,p2,p3:vec3_t);stdcall;external V_LIB_DLL;
procedure	dxfClose(dxf:file_t);stdcall;external V_LIB_DLL;

(*  =================================================================== *)
(*  v_str.h                                                             *)

(*
 *  strvCopy - analog to strncpy.
 *  Differences:
 *  1. Third parameter is AMOUNT OF MEMORY allocated for 'dst'.
 *  2. 'Dst' is ALWAYS terminated by null-character ('\0').
 *  3. Strings 'dst' and 'src' can be overlapped.
 *  4. Ifdef CHECHED_BUILD and dst==NULL, default static buffer returned.
 *)
function    strvCopy(dst,src:pchar;dest_storage_len:integer):pchar;
  stdcall;external V_LIB_DLL name 'strCopy';
(*
 *  strvCat - analog to strncat.
 *  Differences:
 *  1. Strings 'dst' and 'src' can be overlapped.
 *  2. Ifdef CHECHED_BUILD and dst==NULL, default static buffer returned.
 *)
function    strvCat(dst,src:pchar;max_chars_to_be_added:integer):pchar;
  stdcall;external V_LIB_DLL name 'strCat';
(*
 *  Strips leading whitespace from string. Returns str.
 *  Note. Ifdef CHECHED_BUILD and str==NULL, default static buffer returned.
 *)
function    strvStripLead(str:pchar):pchar;
  stdcall;external V_LIB_DLL name 'strStripLead';
(*
 *  Strips trailing whitespace from string. Returns str.
 *  Note. Ifdef CHECHED_BUILD and str==NULL, default static buffer returned.
 *)
function    strvStripTail(str:pchar):pchar;
  stdcall;external V_LIB_DLL name 'strStripTail';
(*
 *  Strips both leading and trailing whitespace. Returns str.
 *  Note. Ifdef CHECHED_BUILD and str==NULL, default static buffer returned.
 *)
function    strvStripLT(str:pchar):pchar;
  stdcall;external V_LIB_DLL name 'strStripLT';
(*  Returns new memAlloc()'ed copy of 'str' *)
function    strvDup(str:pchar):pchar;
  stdcall;external V_LIB_DLL name 'strDup';
(*  =================================================================== *)
(*  v_stack.h                                                           *)

type
  u8_stack_p      = ^u8_stack_t;
  u8_stack_t      = record
    n_elem      : u32_t;
    next_elem   : u32_t;
    buf         : u8_t_array_p;
  end;
  
  vp_stack_p      = ^u8_stack_t;
  vp_stack_t      = record
    n_elem      : u32_t;
    next_elem   : u32_t;
    buf         : void_p_array_p;
  end;

  stack_p         = ^stack_t;
  stack_t         = record
    n_elem          : u32_t;
    next_elem       : u32_t;
    element_size    : u32_t;
    buf,ptr         : void_p;
  end;
  
(*  Initializes all fields of struct <type>_stack_s with zeros *)
procedure   u8sInit(var stack:u8_stack_t);stdcall;external V_LIB_DLL;
procedure   vpsInit(var stack:vp_stack_t);stdcall;external V_LIB_DLL;
(*  Releases stack's storage and sets size of stack to zero *)
procedure   u8sClear(var stack:u8_stack_t);stdcall;external V_LIB_DLL;
procedure   vpsClear(var stack:vp_stack_t);stdcall;external V_LIB_DLL;
(*  Pushes one element *)
procedure   u8sPush(var stack:u8_stack_t;element:u8_t);
  stdcall;external V_LIB_DLL;
procedure   vpsPush(var stack:vp_stack_t;element:void_p);
  stdcall;external V_LIB_DLL;
(*  Pushes buffer of num_elements elements *)
procedure   u8sPushBuffer(var stack:u8_stack_t;src:u8_t_array_p;
  num_elements:u32_t);stdcall;external V_LIB_DLL;
procedure   vpsPushBuffer(var stack:vp_stack_t;src:void_p_array_p;
  num_elements:u32_t);stdcall;external V_LIB_DLL;
(*  Pops one element, return 1 on success *)
function    u8sPop(var stack:u8_stack_t;var element:u8_t):vboolean;
  stdcall;external V_LIB_DLL;
function    vpsPop(var stack:vp_stack_t;var element:void_p):vboolean;
  stdcall;external V_LIB_DLL;
(*  Pops buffer of num_elements, returns number of elements *)
function    u8sPopBuffer(var stack:u8_stack_t;dst:u8_t_array_p;
  num_elements:u32_t):vboolean;stdcall;external V_LIB_DLL;
function    vpsPopBuffer(var stack:vp_stack_t;dst:void_p_array_p;
  num_elements:u32_t):vboolean;stdcall;external V_LIB_DLL;
(* Sets element at pos; if storage too small, resizes it. *)
function    u8sSet(var stack:u8_stack_t;pos:u32_t;element:u8_t):vboolean;
  stdcall;external V_LIB_DLL;
function    vpsSet(var stack:vp_stack_t;pos:u32_t;element:void_p):vboolean;
  stdcall;external V_LIB_DLL;
(*  Concatenates two stacks; src unchanged *)
procedure   u8sConcat(var dst,src:u8_stack_t);stdcall;external V_LIB_DLL;
procedure   vpsConcat(var dst,src:vp_stack_t);stdcall;external V_LIB_DLL;
(*  Resizes stack. If newsize less than stack's size of storage, than 
 *  xxaResize() affects only TOS (stack->next_elem); otherwise new 
 *  storage (of size => newsize) allocated. Old contens of stack
 *  unchanged. If newsize greater then TOS, than 
 *  function adds (newsize-size) zeros after old TOS.
 *)
procedure   u8sResize(var stack:u8_stack_t;newsize:u32_t);
  stdcall;external V_LIB_DLL;
procedure   vpsResize(var stack:u8_stack_t;newsize:u32_t);
  stdcall;external V_LIB_DLL;
(*  Frees all unused memory *)
procedure   u8sTrim(var stack:u8_stack_t);stdcall;external V_LIB_DLL;
procedure   vpsTrim(var stack:vp_stack_t);stdcall;external V_LIB_DLL;

function    u8sCount(var stack:u8_stack_t):u32_t;
function    vpsCount(var stack:vp_stack_t):u32_t;
(*  Returns element at pos (NO CHECKS PERFORMED !) *)
function    u8sGet(var stack:u8_stack_t;pos:u32_t):u8_t;
function    vpsGet(var stack:vp_stack_t;pos:u32_t):void_p;
(*  Returns stack's storage. Don't duplicate it because it can be 
 *  invalidated in any call of Push/Set/Resize functions.
 *)
function    u8sGetStorage(var stack:u8_stack_t):u8_t_array_p;
function    vpsGetStorage(var stack:vp_stack_t):void_p_array_p;
(* Stores new object in first non-NULL position *)
function    vpsStore(var stack:vp_stack_t;ptr:pointer):u32_t;
  stdcall;external V_LIB_DLL;
function    vpsFind(var stack:vp_stack_t;ptr:pointer;
  pos_return:u32_p):vboolean;stdcall;external V_LIB_DLL;

procedure   stackInit(var stack:stack_t;element_size:u32_t);
  stdcall;external V_LIB_DLL;
procedure   stackClear(var stack:stack_t);stdcall;external V_LIB_DLL;
(* Pushes element_size bytes from element *)
procedure   stackPush(var stack:stack_t;element:void_p);
  stdcall;external V_LIB_DLL;
(* Pushes (element_size * num_elements) bytes from buffer *)
procedure   stackPushBuffer(var stack:stack_t;src:void_p;
  num_elements:u32_t);stdcall;external V_LIB_DLL;
(* Pops element_size bytes to element *)
function    stackPop(var stack:stack_t;element:void_p):vboolean;
  stdcall;external V_LIB_DLL;
(* Pops (element_size * num_elements) bytes to dst *)
function    stackPopBuffer(var stack:stack_t;dst:void_p;
  num_elements:u32_t):vboolean;stdcall;external V_LIB_DLL;
(* Copies element_size bytes from element to the position of 
 * element #pos; if stack too small, resizes it *)
procedure   stackSet(var stack:stack_t;pos:u32_t;element:void_p);
  stdcall;external V_LIB_DLL;
procedure   stackConcat(var dst,src:stack_t);stdcall;external V_LIB_DLL;
procedure   stackResize(var stack:stack_t;newsize:u32_t);
  stdcall;external V_LIB_DLL;
procedure   stackTrim(var stack:stack_t);stdcall;external V_LIB_DLL;
function    stackCount(var stack:stack_t):u32_t;
(* Copies element_size bytes from position of element #pos to dst *)
procedure   stackGet(var stack:stack_t;dst:void_p;pos:u32_t);
function    stackGetStorage(var stack:stack_t):void_p;

(*  =================================================================== *)
(*  v_fifo.h                                                            *)

type
  u8_fifo_p   = ^u8_fifo_t;
  u8_fifo_t   = record
    size    : u32_t;
    head    : u32_t;
    tail    : u32_t;
    avail   : u32_t;
    buf     : u8_t_array_p;
  end;
  
  fifo_p      = ^fifo_t;
  fifo_t      = record
    element_size    : u32_t;
    size            : u32_t;
    avail           : u32_t;
    buf,head,tail,limit : char_p;
  end;

procedure   u8fInit(var fifo:u8_fifo_t);stdcall;external V_LIB_DLL;
procedure   fifoInit(var fifo:fifo_t;element_size:u32_t);
  stdcall;external V_LIB_DLL;
procedure   u8fPush(var fifo:u8_fifo_t;element:u8_t);
  stdcall;external V_LIB_DLL;
procedure   fifoPush(var fifo:fifo_t;element:void_p);
  stdcall;external V_LIB_DLL;
procedure   u8fPushBuffer(var fifo:u8_fifo_t;src:u8_t_array_p;
  num_elements:u32_t);stdcall;external V_LIB_DLL;
function    u8fPop(var fifo:u8_fifo_t;var element:u8_t):vboolean;
  stdcall;external V_LIB_DLL;
function    fifoPop(var fifo:fifo_t;element:void_p):vboolean;
  stdcall;external V_LIB_DLL;
function    u8fPopBuffer(var fifo:u8_fifo_t;dst:u8_t_array_p;
  num_elements:u32_t):integer;stdcall;external V_LIB_DLL;
procedure   u8fClear(var fifo:u8_fifo_t);stdcall;external V_LIB_DLL;
procedure   fifoClear(var fifo:fifo_t);stdcall;external V_LIB_DLL;
procedure   u8fPurge(var fifo:u8_fifo_t);stdcall;external V_LIB_DLL;
procedure   fifoPurge(var fifo:fifo_t);stdcall;external V_LIB_DLL;

function    u8fCount(var fifo:u8_fifo_t):u32_t;
function    fifoCount(var fifo:fifo_t):u32_t;

(*  =================================================================== *)
(*  v_btree.h                                                           *)

type
  btree_p         = ^btree_t;
  btree_t         = record
    data        : pointer;
    parent      : btree_p;
    children    : array[0..1] of btree_p;
  end;
  traverse_proc_t = procedure(node_data:pointer);stdcall;

function    btAllocNode(data:pointer;parent:btree_p;
  child_index:integer):btree_p;stdcall;external V_LIB_DLL;
function    btStore(data:pointer;len:u32_t;parent:btree_p;
  child_index:integer):btree_p;stdcall;external V_LIB_DLL;
function    btRootNode(any_leaf:btree_p):btree_p;
  stdcall;external V_LIB_DLL;
procedure   btDeleteAllNodes(root:btree_p;destr_proc:traverse_proc_t);
  stdcall;external V_LIB_DLL;

(*  =================================================================== *)
(*  v_wmf.h                                                             *)

type
  gl_tl_callbacks_p = ^gl_tl_callbacks_t;
  gl_tl_callbacks_t = record
    point           : procedure(dev:pointer;v:vec3_t;c:color4b_t;st:vec2_t);stdcall;
    line            : procedure(dev:pointer;v1:vec3_t;c1:color4b_t;st1:vec2_t;
      v2:vec3_t;c2:color4b_t;st2:vec2_t);stdcall;
    begin_polygon   : procedure(dev:pointer;numvert:integer);stdcall;
    polygon_vertex  : procedure(dev:pointer;v:vec3_t;c:color4b_t;st:vec2_t);stdcall;
    pass_through    : procedure(dev:pointer;numvert:integer);stdcall;
  end;
  
function  metaCreateRenderer(outfile_name:PChar;
  mmWidth,mmHeight:u32_t):vhandle_t;stdcall;external V_LIB_DLL;
function  metaCreateRendererEx(outfile_name:PChar;mmWidth,mmHeight:u32_t;
  LogicalWidth,LogicalHeight:vec_t;
  DeviceWidth,DeviceHeight:s16_t):vhandle_t;
  stdcall;external V_LIB_DLL;
procedure metaDestroyRenderer(handle:vhandle_t);stdcall;external V_LIB_DLL;
procedure metaClearBuffer(handle:vhandle_t);stdcall;external V_LIB_DLL;
function  metaGetRefAPI(handle:vhandle_t):gl_tl_callbacks_p;stdcall;external V_LIB_DLL;

{$IFNDEF  CONFIG_GDI_EMULATION}
function  metaGetMaxXNP(handle:vhandle_t):u32_t;stdcall;external V_LIB_DLL;
function  metaGetMaxYNP(handle:vhandle_t):u32_t;stdcall;external V_LIB_DLL;
function  metaGetHandleNP(handle:vhandle_t):HDC;stdcall;external V_LIB_DLL;
procedure metaGetExtentNP(handle:vhandle_t;str:PChar;var cx,cy:u32_t);
  stdcall;external V_LIB_DLL;
procedure metaChangeFontNP(handle:vhandle_t;char_height,deg_ori,weight,
  italic:integer;face:PChar);stdcall;external V_LIB_DLL;
{$ENDIF   !CONFIG_GDI_EMULATION}

(*
 * Low-level support for OpenGL capture. Insted these, consider
 * using vglDrawToMetafile().
 *)
function  metaBeginCapture(file_name:PChar;mmWidth,mmHeight:u32_t):
  vhandle_t;stdcall;external V_LIB_DLL;
function  metaDrawAgain(handle:vhandle_t):vboolean;
  stdcall;external V_LIB_DLL;
function  metaFinishCapture(handle:vhandle_t):vboolean;
  stdcall;external V_LIB_DLL;
(*  =================================================================== *)
(*  v_input.h                                                           *)
(*  Input events *)
type
  input_event_t           = integer;
  keycode_t               = integer;

const
  ev_key_down             = 0;
  ev_key_up               = 1;
  ev_mouse_down           = 2;
  ev_mouse_up             = 3;
  ev_mouse_move           = 4;
  ev_paint                = 5;
  ev_size                 = 6;
  ev_move                 = 7;

(*
 * LibV keymapping
 *)
const
  key_unknown             = 0;

  key_escape              = 1;
  key_1                   = 2;
  key_2                   = 3;
  key_3                   = 4;
  key_4                   = 5;
  key_5                   = 6;
  key_6                   = 7;
  key_7                   = 8;
  key_8                   = 9;
  key_9                   = 10;
  key_0                   = 11;
  key_minus               = 12;
  key_equal               = 13;
  key_backspace           = 14;
  key_tab                 = 15;
  key_Q                   = 16;
  key_W                   = 17;
  key_E                   = 18;
  key_R                   = 19;
  key_T                   = 20;
  key_Y                   = 21;
  key_U                   = 22;
  key_I                   = 23;
  key_O                   = 24;
  key_P                   = 25;
  key_left_bracket        = 26;
  key_right_bracket       = 27;
  key_enter               = 28;
  key_left_control        = 29;
  key_A                   = 30;
  key_S                   = 31;
  key_D                   = 32;
  key_F                   = 33;
  key_G                   = 34;
  key_H                   = 35;
  key_J                   = 36;
  key_K                   = 37;
  key_L                   = 39;
  key_colon               = 40;
  key_apostrophe          = 41;
  key_back_quote          = 42;
  key_left_shift          = 43;
  key_back_slash          = 44;
  key_Z                   = 45;
  key_X                   = 46;
  key_C                   = 47;
  key_V                   = 48;
  key_B                   = 49;
  key_N                   = 50;
  key_M                   = 51;
  key_comma               = 52;
  key_dot                 = 53;
  key_slash               = 54;
  key_right_shift         = 55;
  key_printscreen         = 56;
  key_left_alt            = 57;
  key_space               = 58;
  key_capslock            = 59;
  key_f1                  = 60;
  key_f2                  = 61;
  key_f3                  = 62;
  key_f4                  = 63;
  key_f5                  = 64;
  key_f6                  = 65;
  key_f7                  = 66;
  key_f8                  = 67;
  key_f9                  = 68;
  key_f10                 = 69;

  key_numlock             = 70;
  key_scrolllock          = 71;
  key_home                = 72;
  key_up                  = 73;
  key_pageup              = 74;
  key_grey_minus          = 75;
  key_left                = 76;
  key_numpad_5            = 77;
  key_right               = 78;
  key_grey_plus           = 79;
  key_end                 = 80;
  key_down                = 81;
  key_pagedown            = 82;
  key_insert              = 83;
  key_delete              = 84;

  key_grey_slash          = 85;
  key_grey_asterisk       = 86;
  key_pause               = 87;

  key_right_control       = 88;
  key_right_alt           = 89;
  key_grey_enter          = 90;
  key_numpad_7            = 91;
  key_numpad_8            = 92;
  key_numpad_9            = 93;
  key_numpad_4            = 94;
  key_numpad_6            = 95;
  key_numpad_1            = 96;
  key_numpad_2            = 97;
  key_numpad_3            = 98;
  key_numpad_0            = 99;
  key_numpad_dot          = 100;

  key_left_win            = 101;
  key_right_win           = 102;
  key_context             = 103;

  key_f11                 = 104;
  key_f12                 = 105;

  key_left_mouse          = 106;
  key_middle_mouse        = 107;
  key_right_mouse         = 108;

  key_maxcode             = 109;

(*
 * Input record
 *)
type
  input_record_p          = ^input_record_t;
  input_record_t          = record
    event               : input_event_t;
    first_code          : s32_t;
    second_code         : s32_t;
    time                : vec_t;
  end;

(*
 * Thread input state
 *)
const
  input_locale_english      = 0;
  input_locale_russian      = 1;
  input_locale_russian_koi8 = 2;

type
  input_state_p = ^input_state_t;
  input_state_t = record
    locale      : integer;
    numlock     : vboolean;
    capslock    : vboolean;
    scrolllock  : vboolean;
    control     : vboolean;
    shift       : vboolean;
    meta        : vboolean;
  end;

function keycodeGetName(kcode:keycode_t):PChar;stdcall;external V_LIB_DLL;
function keycodeGetCode(kname:PChar):keycode_t;stdcall;external V_LIB_DLL;
function inputKeycodeToChar(key:keycode_t):char;stdcall;external V_LIB_DLL;
function inputState:input_state_p;stdcall;external V_LIB_DLL;

(*  =================================================================== *)
(*  v_camctl.h                                                          *)

type
  cam_p               = ^cam_t;
  cam_t               = record
    origin          : vec3_t;
    target          : vec3_t;
    target_distances : vec2_t;
    targeted        : vboolean;
    baseplane       : plane3_t;
    baseplane_distances : vec2_t;
    snapped         : vboolean;
    dir             : vec3_t;
    up              : vec3_t;
    angles          : vec3_t;
    transform       : matrix3x4_t;
    gl_transform    : matrix4_t;
    modified        : vboolean;
  end;

  sdof_control_p          = ^sdof_control_t;
  sdof_control_t          = record
    step                : vec3_t;
    speed               : vec3_t;
    zero_speed          : vec3_t;
    max_speed           : vec3_t;
    fade_accel          : vec3_t;
    accel               : vec3_t;
    angle_step          : vec3_t;
    angle_speed         : vec3_t;
    zero_angle_speed    : vec3_t;
    max_angle_speed     : vec3_t;
    fade_angle_accel    : vec3_t;
    angle_accel         : vec3_t;
  end;

  sdof_keymap_p           = ^sdof_keymap_t;
  sdof_keymap_t           = record
    timer               : timer_t;

    move_forward, move_backward : keycode_t;
    move_right, move_left       : keycode_t;
    move_up, move_down          : keycode_t;

    stepping_forward, stepping_backward : vboolean;
    stepping_right, stepping_left       : vboolean;
    stepping_up, stepping_down          : vboolean;

    moving_forward, moving_backward     : vboolean;
    moving_right, moving_left           : vboolean;
    moving_up, moving_down              : vboolean;
    moving_times                        : vec3_t;

    yaw_left, yaw_right                 : keycode_t;
    pitch_up, pitch_down                : keycode_t;
    roll_cw, roll_ccw                   : keycode_t;

    yawing_left, yawing_right           : vboolean;
    pitching_up, pitching_down          : vboolean;
    rolling_cw, rolling_ccw             : vboolean;
    rotation_times                      : vec3_t;

    mouse_x_index                       : integer;
    mouse_y_index                       : integer;
    angle_axis                          : vec3_t;
    motion_axis                         : vec3_t;
  end;

  mouse_drag_control_p    = ^mouse_drag_control_t;
  mouse_drag_control_t    = record
    emulate_three_buttons   : vboolean;
    begin_drag              : vboolean;
    m_key                   : keycode_t;
    p_x, p_y                : s32_t;
  end;

procedure   camInit(var cam:cam_t);stdcall;external V_LIB_DLL;
procedure   camGetTransform(var cam:cam_t;var dest:matrix3x4_t);
  stdcall;external V_LIB_DLL;
procedure   camLoadGLTransform(var cam:cam_t);
  stdcall;external V_LIB_DLL;
procedure   camChangeOrigin(var cam:cam_t;var pos:vec3_t);
  stdcall;external V_LIB_DLL;
procedure   camChangeDir(var cam:cam_t;var dir:vec3_t);
  stdcall;external V_LIB_DLL;
procedure   camChangeUp(var cam:cam_t;var up:vec3_t);
  stdcall;external V_LIB_DLL;
procedure   camSetTarget(var cam:cam_t;var target:vec3_t);
  stdcall;external V_LIB_DLL;
procedure   camLookAt(var cam:cam_t;var look_at:vec3_t);
  stdcall;external V_LIB_DLL;
(* Don't confuse with camSetTarget() *)
procedure   camTargetObject(var cam:cam_t;var target_object:vec3_t);
  stdcall;external V_LIB_DLL;
(* rotation order: 1, 0, 2. *)
procedure   camDirAndUpFromAngles(var cam:cam_t;var angles:vec3_t);
  stdcall;external V_LIB_DLL;

procedure   sdcInit(var sdc:sdof_control_t);stdcall;external V_LIB_DLL;
procedure   sdcSetStep(var sdc:sdof_control_t;var step:vec3_t);
  stdcall;external V_LIB_DLL;
procedure   sdcSetMaxSpeed(var sdc:sdof_control_t;var speed:vec3_t);
  stdcall;external V_LIB_DLL;
procedure   sdcSetAccel(var sdc:sdof_control_t;var accel:vec3_t);
  stdcall;external V_LIB_DLL;
procedure   sdcSetAngleStep(var sdc:sdof_control_t;var angle_step:vec3_t);
  stdcall;external V_LIB_DLL;
procedure   sdcSetMaxAngleSpeed(var sdc:sdof_control_t;
  var angle_speed:vec3_t);stdcall;external V_LIB_DLL;
procedure   sdcSetAngleAccel(var sdc:sdof_control_t;
  var angle_accel:vec3_t);stdcall;external V_LIB_DLL;
procedure   sdcSyncronize(var km:sdof_keymap_t;var sdc:sdof_control_t;
  var cam:cam_t);stdcall;external V_LIB_DLL;
procedure   sdckInit(var km:sdof_keymap_t);stdcall;external V_LIB_DLL;
function    sdckProcessKey(var km:sdof_keymap_t;event:input_event_t;
  code:keycode_t):vboolean;stdcall;external V_LIB_DLL;
function    sdckProcessMouse(var km:sdof_keymap_t;
  var in_rec:input_record_t):vboolean;stdcall;external V_LIB_DLL;
function    sdofMouseDragControl(var km:sdof_keymap_t;
  var ctl:mouse_drag_control_t;var cam:cam_t;var in_rec:input_record_t):
  vboolean;stdcall;external V_LIB_DLL;

(*  =================================================================== *)
(*  v_gl.h                                                              *)

type
  gl_font_adjustment_t    = integer;

(*
 * Font adjustments
 *)
const
  fa_left_top         = 0;
  fa_center_top       = 1;
  fa_right_top        = 2;
  fa_left_center      = 3;
  fa_center_center    = 4;
  fa_right_center     = 5;
  fa_left_bottom      = 6;
  fa_center_bottom    = 7;
  fa_right_bottom     = 8;
  fa_custom           = 9;

(*
 * Callback to pass to vglDrawToMetafile
 *)
type
  draw_proc_t = procedure(param:pointer);stdcall;


function  vglCreateWindow(title:pchar;x,y,width,height:u32_t):vhandle_t;
  stdcall;external V_LIB_DLL;
function  vglCreateFullscreenWindow(title:pchar;
  hres,vres,bpp,refresh_rate:u32_t):vhandle_t;stdcall;external V_LIB_DLL;
function  vglCreateChildWindow(title:pchar;x,y,width,height:u32_t;
  parent:HWND):vhandle_t;stdcall;external V_LIB_DLL;
function  vglCreateMappedWindow(width,height:u32_t):vhandle_t;
  stdcall;external V_LIB_DLL;
procedure vglDestroyWindow(win:vhandle_t);stdcall;external V_LIB_DLL;
function  vglMakeCurrent(win:vhandle_t):vboolean;stdcall;external V_LIB_DLL;
function  vglQueryExtension(extension:PChar;var entry:pointer):vboolean;
  stdcall;external V_LIB_DLL;
function  vglGetCurrentWindow:vhandle_t;stdcall;external V_LIB_DLL;
function  vglPending:vboolean;stdcall;external V_LIB_DLL;
function  vglNextEvent(var ev:input_record_t):vboolean;
  stdcall;external V_LIB_DLL;
procedure vglSwapBuffers;stdcall;external V_LIB_DLL;
(* vglReadPixels() returns memAlloc()'ed block *)
function  vglReadPixels(var width,height:u32_t):void_p;
  stdcall;external V_LIB_DLL;
function  vglHideWindow:Boolean;stdcall;external V_LIB_DLL;
function  vglShowWindow:Boolean;stdcall;external V_LIB_DLL;
procedure vglSetFocus;stdcall;external V_LIB_DLL;
function  vglResizeWindow(width,height:integer):vboolean;
  stdcall;external V_LIB_DLL;
function  vglMoveWindow(left,top:integer):vboolean;
  stdcall;external V_LIB_DLL;
procedure vglCapturePointer(capture:vboolean);
  stdcall;external V_LIB_DLL;
(*
 * BGI font loading
 *)
function  vglLoadBGIFontEx(file_name:PChar;load_as_koi8:vboolean):
  vhandle_t;stdcall;external V_LIB_DLL;
function  vglLoadBGIFont(file_name:PChar):vhandle_t;
  stdcall;external V_LIB_DLL;
procedure vglDeleteFont(fnt:vhandle_t);stdcall;external V_LIB_DLL;
procedure vglSelectFont(fnt:vhandle_t);stdcall;external V_LIB_DLL;
procedure vglSetFontAdjustment(fnt:vhandle_t;
  adjustment:gl_font_adjustment_t);stdcall;external V_LIB_DLL;
procedure vglSetFontCustomAdjustment(fnt:vhandle_t;
  var custom_adjustment:vec3_t);stdcall;external V_LIB_DLL;
procedure vglSetFontScale(fnt:vhandle_t;scale:vec_t);
  stdcall;external V_LIB_DLL;
procedure vglSetFontFOV(fnt:vhandle_t;fov:vec_t);
  stdcall;external V_LIB_DLL;

{$IFDEF	CONFIG_GL_PRECOMPILED_FONT}
(*
 * Selects compiled-in simple stroke font.
 * Before this call, OpenGL context must be initialized via
 * vglCreateWindowXXX().
 *)
procedure vglLoadDefaultFontEx(load_as_koi8:vboolean);
	stdcall;external V_LIB_DLL;
(* Same as above, uses Win1251 code table *)
procedure vglLoadDefaultFont;stdcall;external V_LIB_DLL;
{$ENDIF} {CONFIG_GL_PRECOMPILED_FONT}

procedure vglPuts(str:pchar);stdcall;external V_LIB_DLL;
procedure vglPrintf(fmt:pchar;const args:array of const);
procedure vglDrawString(var origin:vec3_t;var cam:cam_t;text:PChar);
  stdcall;external V_LIB_DLL;
(*
 * Feedback buffer -> Windows metafile translation
 *)
function  vglDrawToMetafile(file_name:PChar;mmWidth,mmHeight:u32_t;
  DrawScene:draw_proc_t;param:pointer):vboolean;
  stdcall;external V_LIB_DLL;
(*
 * Framebuffer -> raster image translation
 *)
function  vglSaveFramebuffer(file_name:PChar;mmWidth,mmHeight:u32_t):
  vboolean;stdcall;external V_LIB_DLL;
(*
 * GL 1.1 texturing
 *)
type
  skybox_t = array[0..5] of GLuint;
function  vglLoadTexture(file_name:PChar;load_pros:image_load_proc_t;
  filter,clamp,env:GLenum):GLuint;stdcall;external V_LIB_DLL;
(*
 * Loads six textures for skybox
 * (deals nothing with NV_CUBE_MAP ext)
 *)
function  vglLoadSkyBoxTextures(var dest:skybox_t;path,sky_name,file_ext:PChar):
  vboolean;stdcall;external V_LIB_DLL;
procedure vglDrawSkyBox(var sky_textures:skybox_t;
  sky_intensity,sky_opacity:vec_t);stdcall;external V_LIB_DLL;

(*  =================================================================== *)
(*  v_tlist.h                                                           *)

(*
 * Callback for tlistAddXXX() functions
 *)
type
  vertex_callback_t   = procedure(var v:vec3_t;var c:vec4_t;var n:vec3_t;
    var t:vec2_t;var ef:u32_t;param:pointer);stdcall;

function    tlistCreate:vhandle_t;stdcall;external V_LIB_DLL;
procedure   tlistClear(list:vhandle_t);stdcall;external V_LIB_DLL;
procedure   tlistDestroy(list:vhandle_t);stdcall;external V_LIB_DLL;
procedure   tlistPushMatrix(list:vhandle_t);stdcall;external V_LIB_DLL;
procedure   tlistPopMatrix(list:vhandle_t);stdcall;external V_LIB_DLL;
procedure   tlistLoadMatrix(list:vhandle_t;var new_tos:matrix3x4_t);
  stdcall;external V_LIB_DLL;
procedure   tlistLoadIdentity(list:vhandle_t);stdcall;external V_LIB_DLL;
procedure   tlistMultMatrix(list:vhandle_t;var transform:matrix3x4_t);
  stdcall;external V_LIB_DLL;
procedure   tlistRotatev(list:vhandle_t;radians:vec_t;var axis:vec3_t);
  stdcall;external V_LIB_DLL;
procedure   tlistRotate(list:vhandle_t;radians,ax,ay,az:vec_t);
  stdcall;external V_LIB_DLL;
procedure   tlistTranslatev(list:vhandle_t;var t:vec3_t);
  stdcall;external V_LIB_DLL;
procedure   tlistTranslate(list:vhandle_t;tx,ty,tz:vec_t);
  stdcall;external V_LIB_DLL;
procedure   tlistScalev(list:vhandle_t;var s:vec3_t);
  stdcall;external V_LIB_DLL;
procedure   tlistScale(list:vhandle_t;sx,sy,sz:vec_t);
  stdcall;external V_LIB_DLL;

procedure   tlistColor4(list:vhandle_t;r,g,b,a:vec_t);
  stdcall;external V_LIB_DLL;
procedure   tlistColor4v(list:vhandle_t;var color:vec4_t);
  stdcall;external V_LIB_DLL;
procedure   tlistNormal3(list:vhandle_t;x,y,z:vec_t);
  stdcall;external V_LIB_DLL;
procedure   tlistNormal3v(list:vhandle_t;var n:vec3_t);
  stdcall;external V_LIB_DLL;
procedure   tlistTexCoord2(list:vhandle_t;u,v:vec_t);
  stdcall;external V_LIB_DLL;
procedure   tlistTexCoord2v(list:vhandle_t;var t:vec2_t);
  stdcall;external V_LIB_DLL;
procedure   tlistVertex3(list:vhandle_t;x,y,z:vec_t);
  stdcall;external V_LIB_DLL;
procedure   tlistVertex3v(list:vhandle_t;var v:vec3_t);
  stdcall;external V_LIB_DLL;
procedure   tlistEdgeFlag(list:vhandle_t;flag:u32_t);
  stdcall;external V_LIB_DLL;

procedure   tlistAddMeshObject(list:vhandle_t;mesh:mesh_p;obj_num:u32_t;
  vertex_cb:vertex_callback_t;param:void_p);stdcall;external V_LIB_DLL;
procedure   tlistAddPatch(list:vhandle_t;patch:tripatch_p;
  vertex_cb:vertex_callback_t;param:void_p);stdcall;external V_LIB_DLL;
procedure   tlistConcat(dest,list:vhandle_t;
  vertex_cb:vertex_callback_t;param:void_p);stdcall;external V_LIB_DLL;

procedure   tlistGenerateEdgeInfo(list:vhandle_t);
  stdcall;external V_LIB_DLL;
procedure   tlistGenerateBBox(list:vhandle_t);
  stdcall;external V_LIB_DLL;

procedure   tlistDraw(list:vhandle_t;var viewpoint:vec3_t;
  front_to_back:vboolean);stdcall;external V_LIB_DLL;
procedure   tlistDrawWireFrame(list:vhandle_t);stdcall;external V_LIB_DLL;

(*  =================================================================== *)
(*  v_fbbdraw.h                                                         *)

type
  fbb_p               = ^fbb_t;
  fbb_t               = record
    mins, maxs      : vec3_t;
    cam             : cam_p;
    f_mins, f_maxs  : vec3_t;
    steps           : array[0..2] of u32_t;
    legend          : array[0..2] of PChar;
    draw_axis       : array[0..2] of vboolean;
    draw_ticks      : array[0..2] of vboolean;
    draw_labels     : array[0..2] of vboolean;
    draw_grid       : array[0..2] of vboolean;
    draw_legend     : array[0..2] of vboolean;
    smooth_axes     : vboolean;
    smooth_grids    : vboolean;
    smooth_ticks    : vboolean;
    axis_width      : vec3_t;
    grid_width      : vec3_t;
    ticks_size      : vec3_t;
    axis_color      : array[0..2] of vec4_t;
    grid_color      : array[0..2] of vec4_t;
    ticks_color     : array[0..2] of vec4_t;
    label_color     : array[0..2] of vec4_t;
    legend_color    : array[0..2] of vec4_t;
    label_font      : array[0..2] of vhandle_t;
    legend_font     : array[0..2] of vhandle_t;
  end;

procedure   fbbInit(var fbb:fbb_t);stdcall;external V_LIB_DLL;
procedure   fbbDraw(var fbb:fbb_t);stdcall;external V_LIB_DLL;
procedure   fbbDraw2D(var fbb:fbb_t);stdcall;external V_LIB_DLL;

(*  =================================================================== *)
(*  v_gpsp.h                                                            *)

function  cspCreate(vx,vy:vector_p):vhandle_t;
  stdcall;external V_LIB_DLL;
function  cspInterpolate(handle:vhandle_t;x:vec_t):vec_t;
  stdcall;external V_LIB_DLL;
procedure cspChangeX(handle:vhandle_t;new_x:vector_p);
  stdcall;external V_LIB_DLL;
procedure cspChangeY(handle:vhandle_t;new_y:vector_p);
  stdcall;external V_LIB_DLL;
procedure cspSetBoundaryCondition(handle:vhandle_t;
  zero_2nd_derivative:vboolean;
  deriv_left,deriv_right:vec_t);stdcall;external V_LIB_DLL;
procedure cspDestroy(handle:vhandle_t);
  stdcall;external V_LIB_DLL;
(*
 * Multi-dimensional spline interpolator object.
 * - ndim: dimension of input space;
 * - vt: vector of parameter values (of arbitrary size N; N assumed to be >= 2);
 * - vx: array[0..ndim-1] of vectors [0..N-1] of variables.
 *
 * Note.
 * If first point (vx[0]->elements[0],vx[1]->elements[0],...,vx[ndim-1]->elements[0])
 * and last point (vx[0]->elements[N],vx[1]->elements[N],...,vx[ndim-1]->elements[N])
 * are the same, boundary condition will be changed to 'periodic'
 * (see v_spline.c for dirty implementation details).
 *)
function  cspNdCreate(vt:vector_p;var vx;ndim:u32_t):vhandle_t;
  stdcall;external V_LIB_DLL;
procedure cspNdInterpolate(handle:vhandle_t;t:vec_t;var xa_ret:array of vec_t);
  stdcall;external V_LIB_DLL;
procedure cspNdChangeX(handle:vhandle_t;new_x:array of vector_p);
  stdcall;external V_LIB_DLL;
procedure cspNdDestroy(handle:vhandle_t);
  stdcall;external V_LIB_DLL;
(*  =================================================================== *)
(*  v_wavlib.h                                                          *)
function  wavOpenRead(name:PChar):vhandle_t;stdcall;external V_LIB_DLL;
function  mp3Open(name:PChar):vhandle_t;stdcall;external V_LIB_DLL;
function  wavOpenWrite(name:PChar;num_channels,sampling_frequency,
  bits_per_sample:u32_t):vhandle_t;stdcall;external V_LIB_DLL;
function  wavLoadFile(name:PChar;var num_samples,
  num_channels,sampling_frequency,bits_per_sample:u32_t):pointer;
  stdcall;external V_LIB_DLL;
function  wavNumChannels(handle:vhandle_t):u32_t;
  stdcall;external V_LIB_DLL;
function  wavSamplingFrequency(handle:vhandle_t):u32_t;
  stdcall;external V_LIB_DLL;
function  wavBitsPerSample(handle:vhandle_t):u32_t;
  stdcall;external V_LIB_DLL;
function  wavNumSamples(handle:vhandle_t):u32_t;
  stdcall;external V_LIB_DLL;
(*  =================================================================== *)
(*  v_wavin.h                                                           *)
type
  (*
   * Note: TDrvProgress^ will be called in context of other thread, so
   * no mucking with VCL allowed !
   *)
  TDrvProgress          = procedure(arg : pointer);stdcall;

function    waveCaptureInit(num_channels,sampling_frequency,
    bits_per_sample:u32_t;
    OnProgress:TDrvProgress;OnProgressArg:pointer):vboolean;
    stdcall;external V_LIB_DLL;
function    waveCaptureResume:vboolean;stdcall;external V_LIB_DLL;
procedure   waveCapturePause;stdcall;external V_LIB_DLL;
procedure   waveCaptureShutdown;stdcall;external V_LIB_DLL;
function    waveCaptureBlockMode(blocking:vboolean):vboolean;
  stdcall;external V_LIB_DLL;
{ returns length in BYTES, not samples }
function    waveCaptureLength:u32_t;stdcall;external V_LIB_DLL;
function    waveCaptureGet(var dest_buf;requested_bytes:u32_t):u32_t;
  stdcall;external V_LIB_DLL;
(*  =================================================================== *)
(*  v_wavout.h                                                           *)
function  wavePlaybackOpen(num_channels,frequency,bits_per_sample:u32_t):
  vhandle_t;stdcall;external V_LIB_DLL;
function  wavePlaybackPause(dev:vhandle_t):vboolean;
  stdcall;external V_LIB_DLL;
function  wavePlaybackResume(dev:vhandle_t):vboolean;
  stdcall;external V_LIB_DLL;
function  wavePlaybackReset(dev:vhandle_t):vboolean;
  stdcall;external V_LIB_DLL;
function  wavePlaybackWait(dev:vhandle_t;milliseconds:u32_t):vboolean;
  stdcall;external V_LIB_DLL;
(*  =================================================================== *)
(*  reg.h                                                               *)

type
  reg_hive_t          = integer;

const
  reg_hive_local_user = 0;
  reg_hive_all_users  = 1;

function    regImport(file_name:PChar):vboolean;stdcall;external V_LIB_DLL;
function    regExport(file_name:PChar;hive:reg_hive_t):vboolean;
  stdcall;external V_LIB_DLL;
procedure   regCreate;stdcall;external V_LIB_DLL;
procedure   regShutdown;stdcall;external V_LIB_DLL;
function    regSetKey(key_name:PChar):vboolean;stdcall;external V_LIB_DLL;
function    regGetDword(value_key:PChar;var dest:u32_t):vboolean;
  stdcall;external V_LIB_DLL;
function    regGetString(value_key:Pchar;dest:PChar;
  dest_size:u32_t):vboolean;stdcall;external V_LIB_DLL;
function    regGetBinary(value_key:Pchar;dest:pointer;
  dest_size:u32_t):vboolean;stdcall;external V_LIB_DLL;
function    regSetDword(value_key:Pchar;
  src:u32_t):vboolean;stdcall;external V_LIB_DLL;
function    regSetString(value_key:Pchar;
  src:PChar):vboolean;stdcall;external V_LIB_DLL;
function    regSetBinary(value_key:Pchar;src:pointer;
  src_size:u32_t):vboolean;stdcall;external V_LIB_DLL;
(*  =================================================================== *)
(*  tree.h.                                                             *)

//  TODO

(*  =================================================================== *)

implementation

(*  =================================================================== *)
(*  v_x86.c                                                             *)

{$IFNDEF MSC}

procedure memFill(dst:void_p;value:u32_t;count:s32_t);
begin
  FillChar(dst^,count,value);
end;
  
procedure memFill32(dst:void_p;c:u32_t;dwords:s32_t);
begin
  FillChar(dst^,dwords shl 2,value);
end;

procedure memZero(dst:void_p;count:s32_t);
begin
  FillChar(dst^,count,0);
end;

procedure memZero32(dst:void_p;dwords:s32_t);
begin
  FillChar(dst^,dwords shl 2,0);
end;

procedure memCopy(dst,src:void_p;count:s32_t);
begin
  Move(src^,dst^,count);
end;

procedure memCopy32(dst,src:void_p;dwords:s32_t);
begin
  Move(src^,dst^,dwords shl 2);
end;

procedure v_fsincos(var s,c:vec_t;r:vec_t);
var
  _s,_c:Extended;
begin
  SinCos(r,_s,_c);
  s:=_s;
  c:=_c;
end;

{$ENDIF}    { MSC }

(*  =================================================================== *)
(*  v_math.c                                                            *)

function ToRadians(a:vec_t):vec_t;
begin
  Result:=a*RAD_IN_ANGLE;
end;

function ToDegrees(a:vec_t):vec_t;
begin
  Result:=a*ANGLE_IN_RAD;
end;

procedure vec2Set(var vec:vec2_t;x,y:vec_t);
begin
  vec[0]:=x;
  vec[1]:=y;
end;

procedure vec3Set(var vec:vec3_t;x,y,z:vec_t);
begin
  vec[0]:=x;
  vec[1]:=y;
  vec[2]:=z;
end;

procedure vec4Set(var vec:vec4_t;x,y,z,w:vec_t);
begin
  vec[0]:=x;
  vec[1]:=y;
  vec[2]:=z;
  vec[3]:=w;
end;

procedure vec2Zero(var vec:vec2_t);
begin
  vec[0]:=0.0;
  vec[1]:=0.0;
end;
procedure vec3Zero(var vec:vec3_t);
begin
  vec[0]:=0.0;
  vec[1]:=0.0;
  vec[2]:=0.0;
end;
procedure vec4Zero(var vec:vec4_t);
begin
  vec[0]:=0.0;
  vec[1]:=0.0;
  vec[2]:=0.0;
  vec[3]:=0.0;
end;

procedure vec2Copy(var dst,src:vec2_t);
begin
  dst[0]:=src[0];
  dst[1]:=src[1];
end;

procedure vec3Copy(var dst,src:vec3_t);
begin
  dst[0]:=src[0];
  dst[1]:=src[1];
  dst[2]:=src[2];
end;

procedure vec4Copy(var dst,src:vec4_t);
begin
  dst[0]:=src[0];
  dst[1]:=src[1];
  dst[2]:=src[2];
  dst[3]:=src[3];
end;

procedure vec2Add(var dst,v1,v2:vec2_t);
begin
  dst[0]:=v1[0]+v2[0];
  dst[1]:=v1[1]+v2[1];
end;

procedure vec3Add(var dst,v1,v2:vec3_t);
begin
  dst[0]:=v1[0]+v2[0];
  dst[1]:=v1[1]+v2[1];
  dst[2]:=v1[2]+v2[2];
end;

procedure vec4Add(var dst,v1,v2:vec4_t);
begin
  dst[0]:=v1[0]+v2[0];
  dst[1]:=v1[1]+v2[1];
  dst[2]:=v1[2]+v2[2];
  dst[3]:=v1[3]+v2[3];
end;

procedure vec2Sub(var dst,v1,v2:vec2_t);
begin
  dst[0]:=v1[0]-v2[0];
  dst[1]:=v1[1]-v2[1];
end;

procedure vec3Sub(var dst,v1,v2:vec3_t);
begin
  dst[0]:=v1[0]-v2[0];
  dst[1]:=v1[1]-v2[1];
  dst[2]:=v1[2]-v2[2];
end;

procedure vec4Sub(var dst,v1,v2:vec4_t);
begin
  dst[0]:=v1[0]-v2[0];
  dst[1]:=v1[1]-v2[1];
  dst[2]:=v1[2]-v2[2];
  dst[3]:=v1[3]-v2[3];
end;

procedure vec2Scale(var dst,src:vec2_t;scale:vec_t);
begin
  dst[0]:=src[0]*scale;
  dst[1]:=src[1]*scale;
end;

procedure vec3Scale(var dst,src:vec3_t;scale:vec_t);
begin
  dst[0]:=src[0]*scale;
  dst[1]:=src[1]*scale;
  dst[2]:=src[2]*scale;
end;

procedure vec4Scale(var dst,src:vec4_t;scale:vec_t);
begin
  dst[0]:=src[0]*scale;
  dst[1]:=src[1]*scale;
  dst[2]:=src[2]*scale;
  dst[3]:=src[3]*scale;
end;

procedure vec2Negate(var dst,src:vec2_t);
begin
  dst[0]:=-src[0];
  dst[1]:=-src[1];
end;

procedure vec3Negate(var dst,src:vec3_t);
begin
  dst[0]:=-src[0];
  dst[1]:=-src[1];
  dst[2]:=-src[2];
end;

procedure vec4Negate(var dst,src:vec4_t);
begin
  dst[0]:=-src[0];
  dst[1]:=-src[1];
  dst[2]:=-src[2];
  dst[3]:=-src[3];
end;

procedure vec2NegateSelf(var v:vec2_t);
begin
  v[0]:=-v[0];
  v[1]:=-v[1];
end;

procedure vec3NegateSelf(var v:vec3_t);
begin
  v[0]:=-v[0];
  v[1]:=-v[1];
  v[2]:=-v[2];
end;

procedure vec4NegateSelf(var v:vec4_t);
begin
  v[0]:=-v[0];
  v[1]:=-v[1];
  v[2]:=-v[2];
  v[3]:=-v[3];
end;

function  vec2Dot(var v1,v2:vec2_t):vec_t;
begin
  Result:=v1[0]*v2[0]+v1[1]*v2[1];
end;

function  vec3Dot(var v1,v2:vec3_t):vec_t;
begin
  Result:=v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2];
end;

function  vec4Dot(var v1,v2:vec4_t):vec_t;
begin
  Result:=v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]+v1[3]*v2[3];
end;

function  vec2Abs(var vec:vec2_t):vec_t;
begin
  Result:=sqrt(vec[0]*vec[0]+vec[1]*vec[1]);
end;

function  vec3Abs(var vec:vec3_t):vec_t;
begin
  Result:=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
end;

function  vec4Abs(var vec:vec4_t):vec_t;
begin
  Result:=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]+vec[3]*vec[3]);
end;

procedure vec2Unit(var dst,vec:vec2_t);
var
  rabs : vec_t;
begin
  rabs:=1/sqrt(vec[0]*vec[0]+vec[1]*vec[1]);
  vec2Scale(dst,vec,rabs);
end;

procedure vec3Unit(var dst,vec:vec3_t);
var
  rabs : vec_t;
begin
  rabs:=1/sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
  vec3Scale(dst,vec,rabs);
end;

procedure vec4Unit(var dst,vec:vec4_t);
var
  rabs : vec_t;
begin
  rabs:=1/sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]+vec[3]*vec[3]);
  vec4Scale(dst,vec,rabs);
end;

procedure vec4Homogenize(var dst,vec:vec4_t);
var
  rw : vec_t;
begin
  rw:=1/vec[3];
  dst[0]:=vec[0]*rw;
  dst[1]:=vec[1]*rw;
  dst[2]:=vec[2]*rw;
  dst[3]:=1.0;
end;

function  vec2Cross(var v1,v2:vec2_t):vec_t;
begin
  Result:=v1[0]*v2[1]-v1[1]*v2[0];
end;

function  vec3Mix(var v1,v2,v3:vec3_t):vec_t;
var
  v : vec3_t;
begin
  vec3Cross(v,v1,v2);
  Result:=vec3Dot(v,v3);
end;

function  vec2MinInd(var vec:vec2_t):integer;
var
  l1,l2 : vec_t;
begin
  l1:=Abs(vec[0]);
  l2:=Abs(vec[1]);
  if l1>l2 then Result:=1 else Result:=0;
end;

function  vec2MaxInd(var vec:vec2_t):integer;
var
  l1,l2 : vec_t;
begin
  l1:=Abs(vec[0]);
  l2:=Abs(vec[1]);
  if l1<l2 then Result:=1 else Result:=0;
end;

function  vec3MinInd(var vec:vec3_t):integer;
var
  l0,l1,l2 : vec_t;
begin
  l0:=Abs(vec[0]);
  l1:=Abs(vec[1]);
  l2:=Abs(vec[2]);
  if l0<l1 then begin
  if l0<l2 then
    Result:=0 
  else 
    Result:=2;
  end else begin
  if l1<l2 then
    Result:=1
  else 
    Result:=2;
  end;
end;

function  vec3MaxInd(var vec:vec3_t):integer;
var
  l0,l1,l2 : vec_t;
begin
  l0:=Abs(vec[0]);
  l1:=Abs(vec[1]);
  l2:=Abs(vec[2]);
  if l0>l1 then begin
  if l0>l2 then
    Result:=0 
  else
    Result:=2;
  end else begin
  if l1>l2 then
    Result:=1
  else 
    Result:=2;
  end;
end;

function  vec4MinInd(var vec:vec4_t):integer;
var
  l,min : vec_t;
  i,ret : integer;
begin
  ret:=0;
  min:=Abs(vec[ret]);
  for i:=1 to 3 do begin
  l:=Abs(vec[i]);
  if l<min then begin
    min:=l;
    ret:=i;
  end;
  end;
  Result:=ret;
end;

function  vec4MaxInd(var vec:vec4_t):integer;
var
  l,max : vec_t;
  i,ret : integer;
begin
  ret:=0;
  max:=Abs(vec[ret]);
  for i:=1 to 3 do begin
  l:=Abs(vec[i]);
  if l>max then begin
    max:=l;
    ret:=i;
  end;
  end;
  Result:=ret;
end;

function  IsZero(v:vec_t):vboolean;
begin
  Result:=Abs(v)<FLOAT_ZERO_EPSILON;
end;

function  vec2IsZero(var vec:vec2_t):vboolean;
begin
  Result:=IsZero(vec[0]) and IsZero(vec[1]);
end;

function  vec3IsZero(var vec:vec3_t):vboolean;
begin
  Result:=IsZero(vec[0]) and IsZero(vec[1]) and IsZero(vec[2]);
end;

function  vec4IsZero(var vec:vec4_t):vboolean;
begin
  Result:=IsZero(vec[0]) and IsZero(vec[1]) and IsZero(vec[2])
             and IsZero(vec[3]);
end;

function  vec2IsEqual(var v1,v2:vec2_t):vboolean;
begin
  Result:=IsZero(v1[0]-v2[0]) and IsZero(v1[1]-v2[1]);
end;

function  vec3IsEqual(var v1,v2:vec3_t):vboolean;
begin
  Result:=IsZero(v1[0]-v2[0]) and IsZero(v1[1]-v2[1]) and IsZero(v1[2]-v2[2]);
end;

function  vec4IsEqual(var v1,v2:vec4_t):vboolean;
begin
  Result:=IsZero(v1[0]-v2[0]) and IsZero(v1[1]-v2[1])
  and IsZero(v1[2]-v2[2]) and IsZero(v1[3]-v2[3]);
end;

function  vec2IsEqualEpsilon(var a,b:vec2_t;epsilon:vec_t):vboolean;
var
  dif : vec2_t;
  dis : vec_t;
begin
  vec2Sub(dif,a,b);
  dis:=vec2Abs(dif);
  Result:=dis < epsilon;
end;

function  vec3IsEqualEpsilon(var a,b:vec3_t;epsilon:vec_t):vboolean;
var
  dif : vec3_t;
  dis : vec_t;
begin
  vec3Sub(dif,a,b);
  dis:=vec3Abs(dif);
  Result:=dis < epsilon;
end;

function  vec4IsEqualEpsilon(var a,b:vec4_t;epsilon:vec_t):vboolean;
var
  dif : vec4_t;
  dis : vec_t;
begin
  vec4Sub(dif,a,b);
  dis:=vec4Abs(dif);
  Result:=dis < epsilon;
end;

procedure vec2VecScale(var dst,v1,v2:vec2_t);
begin
  dst[0]:=v1[0]*v2[0];
  dst[1]:=v1[1]*v2[1];
end;

procedure vec3VecScale(var dst,v1,v2:vec3_t);
begin
  dst[0]:=v1[0]*v2[0];
  dst[1]:=v1[1]*v2[1];
  dst[2]:=v1[2]*v2[2];
end;

procedure vec4VecScale(var dst,v1,v2:vec4_t);
begin
  dst[0]:=v1[0]*v2[0];
  dst[1]:=v1[1]*v2[1];
  dst[2]:=v1[2]*v2[2];
  dst[3]:=v1[3]*v2[3];
end;

procedure vec2ZoomIF(var zoom,initial,final:vec2_t);
begin
  zoom[0]:=final[0]/initial[0];
  zoom[1]:=final[1]/initial[1];
end;

procedure vec3ZoomIF(var zoom,initial,final:vec3_t);
begin
  zoom[0]:=final[0]/initial[0];
  zoom[1]:=final[1]/initial[1];
  zoom[2]:=final[2]/initial[2];
end;

procedure vec4ZoomIF(var zoom,initial,final:vec4_t);
begin
  zoom[0]:=final[0]/initial[0];
  zoom[1]:=final[1]/initial[1];
  zoom[2]:=final[2]/initial[2];
  zoom[3]:=final[3]/initial[3];
end;

procedure vec2ToRadians(var dst,src:vec2_t);
begin
  vec2Scale(dst,src,ANGLE_TO_RAD);
end;

procedure vec3ToRadians(var dst,src:vec3_t);
begin
  vec3Scale(dst,src,ANGLE_TO_RAD);
end;

procedure vec4ToRadians(var dst,src:vec4_t);
begin
  vec4Scale(dst,src,ANGLE_TO_RAD);
end;

procedure vec2ToDegrees(var dst,src:vec2_t);
begin
  vec2Scale(dst,src,RAD_TO_ANGLE);
end;

procedure vec3ToDegrees(var dst,src:vec3_t);
begin
  vec3Scale(dst,src,RAD_TO_ANGLE);
end;

procedure vec4ToDegrees(var dst,src:vec4_t);
begin
  vec4Scale(dst,src,RAD_TO_ANGLE);
end;

procedure mat2Zero(var mat:matrix2_t);
begin
  memZero32(@mat,sizeof(vec_t));
end;

procedure mat3Zero(var mat:matrix3_t);
begin
  memZero32(@mat,9 * sizeof(vec_t) shr 2);
end;

procedure mat4Zero(var mat:matrix4_t);
begin
  memZero32(@mat,sizeof(vec_t) shl 2);
end;

procedure mat3x4Zero(var mat:matrix3x4_t);
begin
  memZero32(@mat,3*sizeof(vec_t));
end;

procedure mat2Copy(var dst,src:matrix2_t);
begin
  memCopy32(@dst,@src,sizeof(vec_t));
end;

procedure mat3Copy(var dst,src:matrix3_t);
begin
  memCopy32(@dst,@src,9 * sizeof(vec_t) shr 2);
end;

procedure mat4Copy(var dst,src:matrix4_t);
begin
  memCopy32(@dst,@src,sizeof(vec_t) shl 2);
end;

procedure mat3x4Copy(var dst,src:matrix3x4_t);
begin
  memCopy32(@dst,@src,3*sizeof(vec_t));
end;

procedure mat2Unit(var mat:matrix2_t);
begin
  mat[1][0]:=0.0;
  mat[0][1]:=0.0;
  mat[0][0]:=1.0;
  mat[1][1]:=1.0;
end;

procedure mat3Unit(var mat:matrix3_t);
begin
  mat3Zero(mat);
  mat[0][0]:=1.0;
  mat[1][1]:=1.0;
  mat[2][2]:=1.0;
end;

procedure mat4Unit(var mat:matrix4_t);
begin
  mat4Zero(mat);
  mat[0][0]:=1.0;
  mat[1][1]:=1.0;
  mat[2][2]:=1.0;
  mat[3][3]:=1.0;
end;

procedure mat3x4Unit(var mat:matrix3x4_t);
begin
  mat3x4Zero(mat);
  mat[0][0]:=1.0;
  mat[1][1]:=1.0;
  mat[2][2]:=1.0;
end;

procedure mat2RowFromVec2(var mat:matrix2_t;row:integer;var vec:vec2_t);
begin
  mat[row][0]:=vec[0];
  mat[row][1]:=vec[1];
end;
procedure mat2Transpose(var dst,src:matrix2_t);
begin
  dst[0][0]:=src[0][0];
  dst[0][1]:=src[1][0];
  dst[1][0]:=src[0][1];
  dst[1][1]:=src[1][1];
end;

procedure mat2TransposeSelf(var mat:matrix2_t);
var
  temp  : vec_t;
begin
  temp:=mat[0][1];mat[0][1]:=mat[1][0];mat[1][0]:=temp;
end;

procedure vec3Transform(var vec:vec3_t;var mat:matrix3x4_t);
var
  temp  : vec3_t;
begin
  vec3Copy(temp,vec);
  mat3x4VecMul(vec,mat,temp);
end;

procedure mat3x4ConcatBefore(var dst,transform:matrix3x4_t);
var
  tmp : matrix3x4_t;
begin
  mat3x4MatMul(tmp,transform,dst);
  mat3x4Copy(dst,tmp);
end;

procedure mat3x4ConcatAfter(var dst,transform:matrix3x4_t);
var
  tmp : matrix3x4_t;
begin
  mat3x4MatMul(tmp,dst,transform);
  mat3x4Copy(dst,tmp);
end;

procedure rgbFloatFromByte(var rgb:vec3_t;var brgb:color3b_t);
begin
  rgb[0]:=brgb[0]/255.0;
  rgb[1]:=brgb[1]/255.0;
  rgb[2]:=brgb[2]/255.0;
end;

procedure rgbaFloatFromByte(var rgba:vec4_t;var brgba:color4b_t);
begin
  rgba[0]:=brgba[0]/255.0;
  rgba[1]:=brgba[1]/255.0;
  rgba[2]:=brgba[2]/255.0;
  rgba[3]:=brgba[3]/255.0;
end;

procedure rgbByteFromFloat(var brgb:color3b_t;var rgb:vec3_t);
begin
  brgb[0]:=round(rgb[0]*255);
  brgb[1]:=round(rgb[1]*255);
  brgb[2]:=round(rgb[2]*255);
end;

procedure rgbaByteFromFloat(var brgba:color4b_t;var rgba:vec4_t);
begin
  brgba[0]:=round(rgba[0]*255);
  brgba[1]:=round(rgba[1]*255);
  brgba[2]:=round(rgba[2]*255);
  brgba[3]:=round(rgba[3]*255);
end;

(*  =================================================================== *)
(*  v_vector.h                                                          *)

function vecDot(v1,v2:vector_p):vec_t;
var
  i : integer;
  r : vec_t;
begin
  r:=0;
  i:=0;
  while i < v1^.size do begin
    r:=r+v1^.elements[i]+v2^.elements[i];
    i:=i+1;
  end;
  Result:=r;
end;

function vecAbs(v:vector_p):vec_t;
begin
  Result:=sqrt(vecDot(v,v));
end;

function vecCount(v:vector_p):integer;
begin
  Result:=v^.size;
end;

procedure vecCopy(dst,src:vector_p);
var
  i : integer;
begin
  i:=0;
  while i<dst^.size do
  begin
    dst^.elements[i]:=src^.elements[i];
    i:=i+1;
  end;
end;

procedure vecZero(v:vector_p);
begin
  memZero32(v^.elements,v^.size*sizeof(vec_t) shr 2);
end;

procedure vecUnit(v:vector_p);
var
  ra : vec_t;
begin
  ra:=vecAbs(v);
  if IsZero(ra) then
    exit;
  ra:=1.0/ra;
  vecScale(v,v,ra);
end;

{$IFDEF		VECTOR_EXTRA_GET_SET}
function	vecGetElement(v:vector_p;index:integer):vec_t;
begin
	Result := v^.elements^[index];
end;

procedure	vecSetElement(v:vector_p;index:integer;value:vec_t);
begin
	v^.elements^[index] := value;
end;
{$ENDIF}	{VECTOR_EXTRA_GET_SET}

(*  =================================================================== *)
(*  v_matrix.c                                                          *)

procedure matZero(m:matrix_p);
begin
  memZero32(m^.data,m^.rows*m^.cols*sizeof(vec_t) shr 2);
end;

function    matColCount(m:matrix_p):integer;
begin
  Result:=m^.cols;
end;

function    matRowCount(m:matrix_p):integer;
begin
  Result:=m^.cols;
end;

{$IFDEF		MATRIX_EXTRA_GET_SET}
function	matGetElement(m:matrix_p;irow,icol:integer):vec_t;
begin
	Result := m^.cell^[irow]^[icol];
end;

procedure	matSetElement(m:matrix_p;irow,icol:integer;value:vec_t);
begin
	m^.cell^[irow]^[icol] := value;
end;
{$ENDIF}	{MATRIX_EXTRA_GET_SET}

(*  =================================================================== *)
(*  v_plane.c                                                           *)

procedure poly2AddPoint(w:poly2_p;var pt:vec2_t);
begin
  vec2Copy(w^.rays^[w^.count].origin,pt);
  w^.count:=w^.count+1;
end;

function  line2DistFromPoint(var line:line2_t;var p:vec2_t):vec_t;
begin
  Result:=vec2Dot(p,line.normal)+line.dist;
end;

procedure mat2Rotation(var mat:matrix2_t;radians:vec_t);
var
  s, c : Extended;
begin
  SinCos(radians,s,c);
  mat[0][1]:=s;
  mat[1][0]:=-mat[0][1];
  mat[0][0]:=c;
  mat[1][1]:=mat[0][0];
end;

(*  =================================================================== *)
(*  v_space.c                                                           *)

function  vec3DistFromPlane(var pt:vec3_t;pl:plane3_p):vec_t;
begin
  Result:=vec3Dot(pl^.normal,pt) + pl^.dist;
end;

(*  =================================================================== *)
(*  v_fs.c                                                              *)

procedure   filePrintf(f:file_t;fmt:pchar;const args:array of const);
var
  s : string;
begin
  s:=Format(fmt,args);
  fileWrite(f,pchar(s),Length(s));
end;


(*  =================================================================== *)
(*  v_log.c                                                             *)

procedure conPrintf(fmt:pchar;const args:array of const);
var
  s : string;
begin
  s:=Format(fmt,args);
  conPuts(pchar(s));
end;

procedure conlPrintf(level:integer;fmt:pchar;const args:array of const);
var
  s : string;
begin
  s:=Format(fmt,args);
  conlPuts(level,pchar(s));
end;

(*  =================================================================== *)
(*  v_stack.c                                                           *)
function    u8sCount(var stack:u8_stack_t):u32_t;
begin
  Result:=stack.next_elem;
end;

function    vpsCount(var stack:vp_stack_t):u32_t;
begin
  Result:=stack.next_elem;
end;

function    stackCount(var stack:stack_t):u32_t;
begin
  Result:=stack.next_elem;
end;

function    u8sGet(var stack:u8_stack_t;pos:u32_t):u8_t;
begin
  Result:=stack.buf^[pos];
end;

function    vpsGet(var stack:vp_stack_t;pos:u32_t):void_p;
begin
  Result:=stack.buf^[pos];
end;

function    u8sGetStorage(var stack:u8_stack_t):u8_t_array_p;
begin
  Result:=stack.buf;
end;

function    vpsGetStorage(var stack:vp_stack_t):void_p_array_p;
begin
  Result:=stack.buf;
end;

procedure   stackGet(var stack:stack_t;dst:void_p;pos:u32_t);
var
  src : pointer;
begin
  src:=pointer(u32_t(stack.buf)+stack.element_size);
  memCopy(dst,src,stack.element_size);
end;

function    stackGetStorage(var stack:stack_t):void_p;
begin
  Result:=stack.buf;
end;

(*  =================================================================== *)
(*  v_fifo.c                                                            *)

function    u8fCount(var fifo:u8_fifo_t):u32_t;
begin
  Result:=fifo.size-fifo.avail;
end;

function    fifoCount(var fifo:fifo_t):u32_t;
begin
  Result:=fifo.size-fifo.avail;
end;

(*  =================================================================== *)
(*  v_gl.c                                                              *)

procedure   vglPrintf(fmt:pchar;const args:array of const);
var
  s : string;
begin
  s:=Format(fmt,args);
  vglPuts(pchar(s));
end;

(*  =================================================================== *)

initialization
end.
