/'************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * Ported to FreeBASIC by D.J.Peters (Joshy)                             *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) The GNU Lesser General Public License as published by the Free  *
 *       Software Foundation; either version 2.1 of the License, or (at  *
 *       your option) any later version. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 ************************************************************************'/

/' @defgroup drawstuff DrawStuff
DrawStuff is a library for rendering simple 3D objects in a virtual 
environment, for the purposes of demonstrating the features of ODE.
It is provided for demonstration purposes and is not intended for
production use.

@section Notes

In the virtual world, the z axis is "up" and z=0 is the floor.

The user is able to click+drag in the main window to move the camera:
  * left button - pan and tilt.
  * right button - forward and sideways.
  * left + right button (or middle button) - sideways and up.
'/

#ifndef __DRAWSTUFF_BI__
#define __DRAWSTUFF_BI__

#include "fbgfx.bi"
#include "GL/gl.bi"
#include "GL/glu.bi"

#include "version.bi"
#ifdef __FB_WIN32__
# define APICALL CDECL
# inclib "drawstuffwin"
#else
# define APICALL CDECL
# inclib "drawstufflin"
#endif

' texture numbers
#define DS_NONE   0 'uses the current color instead of a texture
#define DS_WOOD   1

#ifndef dEPSILON
# define dEPSILON 1.192092896e-07
#endif
#ifndef M_PI
# define M_PI (3.14159265358979323846)
#endif
#ifndef NULL
# define NULL 0
#endif
#ifndef RAD_TO_DEG
# define RAD_TO_DEG (180.0/M_PI)
#endif
#ifndef DEG_TO_RAD
# define DEG_TO_RAD (M_PI/180.0)
#endif

/'
 * @struct dsFunctions
 * @brief Set of functions to be used as callbacks by the simulation loop.
 * @ingroup drawstuff
 '/

type dsFunctions
  as integer version                ' put DS_VERSION here
  ' version 1 data
  _start   as sub APICALL                    ' called before sim loop starts
  _step    as sub APICALL (pause as integer) ' called before every frame
  _command as sub APICALL (cmd   as integer) ' called if a command key is pressed
  _stop    as sub APICALL                    ' called after sim loop exits
  ' version 2 data
  as zstring ptr _texturepath ' if nonzero, path to texture files
end type

#define _DS(n) declare sub n APICALL alias #n 
#define _DF(n) declare function n APICALL alias #n 

/'
 * @brief Does the complete simulation.
 * @ingroup drawstuff
 * This function starts running the simulation, and only exits when the simulation is done.
 * Function pointers should be provided for the callbacks.
 * @param argv supports flags like '-notex' '-noshadow' '-pause'
 * @param fn Callback functions.
 '/
_ds(dsSimulationLoop) (argc as integer,argv as zstring ptr ptr,window_width as integer, window_height as integer, pfn as dsFunctions ptr)

/'
 * @brief exit with error message.
 * @ingroup drawstuff
 * This function displays an error message then exit.
 * @param msg format strin, like printf, without the newline character.
 '/
#ifdef __FB_WIN32__
_ds(dsError) (msg as string)

/'
 * @brief exit with error message and core dump.
 * @ingroup drawstuff
 * this functions tries to dump core or start the debugger.
 * @param msg format strin, like printf, without the newline character.
 '/
_ds(dsDebug) (msg as string)

/'
 * @brief print log message
 * @ingroup drawstuff
 * @param msg format string, like printf, without the \n.
 '/
_ds(dsPrint) (msg as string)
#else
_ds(dsError) (msg as zstring ptr, ...)
_ds(dsDebug) (msg as zstring ptr, ...)
_ds(dsPrint) (msg as zstring ptr, ...)
#endif


/'
 * @brief Sets the viewpoint
 * @ingroup drawstuff
 * @param xyz camera position.
 * @param hpr contains heading, pitch and roll numbers in degrees. heading=0
 * points along the x axis, pitch=0 is looking towards the horizon, and
 * roll 0 is "unrotated".
 '/
_ds(dsSetViewpoint) (xyz as single ptr,hpr as single ptr)

/'
 * @brief Gets the viewpoint
 * @ingroup drawstuff
 * @param xyz position
 * @param hpr heading,pitch,roll.
 '/
_ds(dsGetViewpoint) (xyz as single ptr,hpr as single ptr)

/'
 * @brief Stop the simulation loop.
 * @ingroup drawstuff
 * Calling this from within dsSimulationLoop()
 * will cause it to exit and return to the caller. it is the same as if the
 * user used the exit command. using this outside the loop will have no
 * effect.
 '/
_ds(dsStop) ()

/'
 * @brief Get the elapsed time (on wall-clock)
 * @ingroup drawstuff
 * It returns the nr of seconds since the last call to this function.
 '/
_df(dsElapsedTime) () as double

/'
 * @brief Toggle the rendering of textures.
 * @ingroup drawstuff
 * It changes the way objects are drawn. these changes will apply to all further
 * dsDrawXXX() functions. 
 * @param the texture number must be a DS_xxx texture constant.
 * The current texture is colored according to the current color.
 * At the start of each frame, the texture is reset to none and the color is
 * reset to white.
 '/
_ds(dsSetTexture) (texture_number as integer)

/'
 * @brief Set the color with which geometry is drawn.
 * @ingroup drawstuff
 * @param red Red component from 0 to 1
 * @param green Green component from 0 to 1
 * @param blue Blue component from 0 to 1
 '/
_ds(dsSetColor) (r as single, g as single, b as single)

/'
 * @brief Set the color and transparency with which geometry is drawn.
 * @ingroup drawstuff
 * @param alpha Note that alpha transparency is a misnomer: it is alpha opacity.
 * 1.0 means fully opaque, and 0.0 means fully transparent.
 '/
_ds(dsSetColorAlpha) (r as single, g as single, b as single, a as single)

/'
 * @brief Draw a box.
 * @ingroup drawstuff
 * @param pos is the x,y,z of the center of the object.
 * @param R is a 3x3 rotation matrix for the object, stored by row like this:
 *        [ R11 R12 R13 0 ]
 *        [ R21 R22 R23 0 ]
 *        [ R31 R32 R33 0 ]
 * @param sides[] is an array of x,y,z side lengths.
 '/
_ds(dsDrawBox) (p as single ptr, R as single ptr, sides as single ptr)

/'
 * @brief Draw a sphere.
 * @ingroup drawstuff
 * @param pos Position of center.
 * @param R orientation.
 * @param radius
 '/
_ds(dsDrawSphere) (p as single ptr, R as single ptr, radius as single)

/'
 * @brief Draw a triangle.
 * @ingroup drawstuff
 * @param pos Position of center
 * @param R orientation
 * @param v0 first vertex
 * @param v1 second
 * @param v2 third vertex
 * @param solid set to 0 for wireframe
 '/
_ds(dsDrawTriangle) (p as single ptr, R as single ptr, v0 as single ptr, v1 as single ptr, v2 as single ptr, solid as integer)

/'
 * @brief Draw a z-aligned cylinder
 * @ingroup drawstuff
 '/
_ds(dsDrawCylinder) (p as single ptr, R as single ptr, length as single, radius as single)

/'
 * @brief Draw a z-aligned capsule
 * @ingroup drawstuff
 '/
_ds(dsDrawCapsule) (p as single ptr, R as single ptr, length as single, radius as single)
/'
 * @brief Draw a line.
 * @ingroup drawstuff
 '/
_ds(dsDrawLine) (pos1 as single ptr,pos2 as single ptr)

/'
 * @brief Draw a convex shape.
 * @ingroup drawstuff
 '/
_ds(dsDrawConvex) (P as single ptr, R as single ptr, _planes as single ptr, _planecount as integer, _points as single ptr, _pointcount as integer, _polygons as integer ptr)

' these drawing functions are identical to the ones above, 
' except they take * double arrays for `P' and `R'.
_ds(dsDrawBoxD) (P as double ptr, R as double ptr, sides as double ptr)
_ds(dsDrawSphereD) (P as double ptr, R as double ptr, radius as single)
_ds(dsDrawTriangleD) (P as double ptr, R as double ptr, v0 as double ptr, v1 as double ptr, v2 as double ptr, solid as integer)
_ds(dsDrawCylinderD) (P as double ptr, R as double ptr, length as single, radius as single)
_ds(dsDrawCapsuleD) (P as double ptr, R as double ptr, length as single, radius as single)
_ds(dsDrawLineD) (pos1 as double ptr, pos2 as double ptr)
_ds(dsDrawConvexD) (P as double ptr, R as double ptr, _planes as double ptr, _planecount as uinteger, _points as double ptr, _pointcount as uinteger, _polygons  as uinteger ptr)
/'
 * @brief Set the quality with which curved objects are rendered.
 * @ingroup drawstuff
 * Higher numbers are higher quality, but slower to draw. 
 * This must be set before the first objects are drawn to be effective.
 * Default sphere quality is 1, default capsule quality is 3.
 '/
_ds(dsSetSphereQuality) (n as integer) ' default = 1
_ds(dsSetCapsuleQuality) (n as integer) ' default = 3

' Backwards compatible API
#define dsDrawCappedCylinder dsDrawCapsule
#define dsDrawCappedCylinderD dsDrawCapsuleD
#define dsSetCappedCylinderQuality dsSetCapsuleQuality

#endif '__DRAWSTUFF_BI__

