initial commit
@@ -0,0 +1,28 @@
|
||||
# Tries to find FREETYPE2 (http://freetype2.bespin.org) a simple and fast
|
||||
# network library by Lee Salzman
|
||||
#
|
||||
|
||||
SET (FREETYPE2_FOUND FALSE)
|
||||
|
||||
FIND_PATH (FREETYPE2_INCLUDE_DIR freetype/freetype.h /usr/include/ /usr/local/include/ /usr/include/freetype2 /usr/local/include/freetype2 $ENV{FREETYPE2_PATH}/include $ENV{FREETYPE2_INCLUDE_PATH})
|
||||
|
||||
FIND_LIBRARY (FREETYPE2_LIBRARIES NAMES freetype PATHS /usr/lib /usr/local/lib $ENV{FREETYPE2_PATH} $ENV{FREETYPE2_PATH}/lib ENV{FREETYPE2_LIBRARY_PATH})
|
||||
|
||||
IF (FREETYPE2_INCLUDE_DIR AND FREETYPE2_LIBRARIES)
|
||||
SET (FREETYPE2_FOUND TRUE)
|
||||
ENDIF (FREETYPE2_INCLUDE_DIR AND FREETYPE2_LIBRARIES)
|
||||
|
||||
IF (FREETYPE2_FOUND)
|
||||
IF (NOT FREETYPE2_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found FREETYPE2: ${FREETYPE2_LIBRARIES}")
|
||||
ENDIF (NOT FREETYPE2_FIND_QUIETLY)
|
||||
ELSE (FREETYPE2_FOUND)
|
||||
IF (FREETYPE2_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find FREETYPE2")
|
||||
ENDIF (FREETYPE2_FIND_REQUIRED)
|
||||
ENDIF (FREETYPE2_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED (
|
||||
FREETYPE2_INCLUDE_DIR
|
||||
FREETYPE2_LIBRARIES
|
||||
)
|
||||
@@ -0,0 +1,60 @@
|
||||
CMAKE_MINIMUM_REQUIRED (VERSION 2.6)
|
||||
|
||||
LIST( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake )
|
||||
|
||||
FIND_PACKAGE (SDL REQUIRED)
|
||||
FIND_PACKAGE (OpenGL REQUIRED)
|
||||
FIND_PACKAGE (PNG REQUIRED)
|
||||
FIND_PACKAGE (FreeType2 REQUIRED)
|
||||
|
||||
ADD_SUBDIRECTORY ( libraries )
|
||||
|
||||
SET ( ENGINE_SRCS
|
||||
CameraBase.cc
|
||||
ControllerBase.cc
|
||||
EntityBase.cc
|
||||
EntityFactoryBase.cc
|
||||
GameEntityBase.cc
|
||||
ModelBase.cc
|
||||
PhysicsBase.cc
|
||||
PhysicsEntityBase.cc
|
||||
ViewBase.cc
|
||||
EventsBase.cc
|
||||
|
||||
Commands.cc
|
||||
DrawingsGL.cc
|
||||
EngineCommands.cc
|
||||
Variables.cc
|
||||
VariablesCommands.cc
|
||||
SimpleConsoleOverlay.cc
|
||||
Sprite.cc
|
||||
|
||||
Engine.cc
|
||||
Logging.cc
|
||||
)
|
||||
|
||||
INCLUDE_DIRECTORIES (
|
||||
${PROJECT_SOURCE_DIR}
|
||||
libraries/mathlib/
|
||||
libraries/coll2d/include
|
||||
libraries/oglft/
|
||||
${FREETYPE2_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
IF ( WIN32 )
|
||||
ADD_LIBRARY ( Engine STATIC ${ENGINE_SRCS} )
|
||||
ELSE ( WIN32 )
|
||||
ADD_LIBRARY ( Engine SHARED ${ENGINE_SRCS} )
|
||||
ENDIF ( WIN32 )
|
||||
|
||||
TARGET_LINK_LIBRARIES ( Engine
|
||||
${SDL_LIBRARY}
|
||||
${OPENGL_LIBRARIES}
|
||||
${PNG_LIBRARIES}
|
||||
mathlib
|
||||
oglft
|
||||
coll2d
|
||||
)
|
||||
|
||||
ADD_SUBDIRECTORY ( tests )
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
#include "CameraBase.h"
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
/*
|
||||
* Inherited Module functions
|
||||
*/
|
||||
int CameraBase::OnInit (int argc, char* argv[]) {
|
||||
LogDebug ("Camera Init");
|
||||
|
||||
mEye[0] = 0.;
|
||||
mEye[1] = 1.;
|
||||
mEye[2] = 1.;
|
||||
|
||||
mPointOfIntrest[0] = 0.;
|
||||
mPointOfIntrest[1] = 0.;
|
||||
mPointOfIntrest[2] = 0.;
|
||||
|
||||
mUp[0] = 0.;
|
||||
mUp[1] = 1.;
|
||||
mUp[2] = 0.;
|
||||
|
||||
mFOVY = 90.;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CameraBase::OnDestroy () {
|
||||
LogDebug ("Camera Destroy");
|
||||
}
|
||||
|
||||
/*
|
||||
* Module specific functions
|
||||
*/
|
||||
void CameraBase::Update () {
|
||||
glMatrixMode (GL_MODELVIEW);
|
||||
|
||||
glLoadIdentity ();
|
||||
gluLookAt(mEye[0], mEye[1], mEye[2],
|
||||
mPointOfIntrest[0], mPointOfIntrest[1], mPointOfIntrest[2],
|
||||
mUp[0], mUp[1], mUp[2]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
#ifndef _CAMERABASE_H
|
||||
#define _CAMERABASE_H
|
||||
|
||||
#include "Engine.h"
|
||||
|
||||
namespace Engine {
|
||||
|
||||
class Module;
|
||||
|
||||
/** \brief Controls from where the View is looking to
|
||||
*/
|
||||
class CameraBase : public Module {
|
||||
public:
|
||||
/** updates the projection and modelview matrices for the camera */
|
||||
void Update ();
|
||||
float GetFOVY () {
|
||||
return mFOVY;
|
||||
}
|
||||
|
||||
/** sets the point where the camera is looking to */
|
||||
void SetPointOfIntrest (float poi_x, float poi_y, float poi_z) {
|
||||
mPointOfIntrest[0] = poi_x;
|
||||
mPointOfIntrest[1] = poi_y;
|
||||
mPointOfIntrest[2] = poi_z;
|
||||
}
|
||||
/** sets the position where the camera is located */
|
||||
void SetEye (float eye_x, float eye_y, float eye_z) {
|
||||
mEye[0] = eye_x;
|
||||
mEye[1] = eye_y;
|
||||
mEye[2] = eye_z;
|
||||
}
|
||||
/** returns the position of the eye */
|
||||
void GetEye (float *eye_out) {
|
||||
eye_out[0] = mEye[0];
|
||||
eye_out[1] = mEye[1];
|
||||
eye_out[2] = mEye[2];
|
||||
}
|
||||
|
||||
/** sets the up direction of the camera */
|
||||
void SetUp (float up_x, float up_y, float up_z) {
|
||||
mUp[0] = up_x;
|
||||
mUp[1] = up_y;
|
||||
mUp[2] = up_z;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** \brief Initializes the system */
|
||||
int OnInit (int argc, char* argv[]);
|
||||
/** \brief Destroys the system (must be called!) */
|
||||
void OnDestroy ();
|
||||
|
||||
float mPointOfIntrest[3];
|
||||
float mEye[3];
|
||||
float mUp[3];
|
||||
|
||||
float mFOVY;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _CAMERABASE_H
|
||||
@@ -0,0 +1,245 @@
|
||||
#include "Commands.h"
|
||||
|
||||
namespace Engine {
|
||||
|
||||
static Commands *CommandsInstance = NULL;
|
||||
|
||||
void trim_command_str (std::string &command_str) {
|
||||
std::string::size_type start = command_str.find_first_not_of (" \t");
|
||||
if (start != std::string::npos)
|
||||
command_str = command_str.substr (start);
|
||||
|
||||
std::string::size_type end = command_str.find_first_of ("#;\n\r\0");
|
||||
|
||||
if (end != std::string::npos)
|
||||
command_str = command_str.substr (0, end);
|
||||
}
|
||||
|
||||
/*
|
||||
* Inherited Module functions
|
||||
*/
|
||||
int Commands::OnInit (int argc, char* argv[]) {
|
||||
LogDebug ("Commands Init");
|
||||
mErrorString = "";
|
||||
if (CommandsInstance) {
|
||||
LogError ("Commands module already initialized!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
CommandsInstance = this;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void Commands::OnDestroy () {
|
||||
LogDebug ("Commands Destroy");
|
||||
|
||||
if (CommandsInstance)
|
||||
CommandsInstance = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Module specific functions
|
||||
*/
|
||||
std::string Commands::GetCommandName (const std::string &command) {
|
||||
return command.substr (0, command.find_first_of (" ;\n\0"));
|
||||
}
|
||||
|
||||
std::vector<std::string> Commands::ParseArgs (std::string &argument_str) {
|
||||
std::vector<std::string> args;
|
||||
std::string::size_type pos = argument_str.find_first_not_of (" ");
|
||||
std::string::size_type next_token = 0;
|
||||
|
||||
while ( argument_str.length ()> pos && argument_str.find_first_of (" \"", pos) != std::string::npos) {
|
||||
next_token = argument_str.find_first_of (" \"", pos);
|
||||
|
||||
if (next_token != std::string::npos && argument_str[next_token] =='"') {
|
||||
pos = next_token;
|
||||
next_token = argument_str.find_first_of ('"', pos + 1);
|
||||
if (next_token != std::string::npos) {
|
||||
args.push_back (argument_str.substr (pos + 1, next_token - pos - 1));
|
||||
}
|
||||
pos = argument_str.find_first_not_of (" ", next_token + 1);
|
||||
|
||||
} else {
|
||||
args.push_back (argument_str.substr (pos, next_token - pos));
|
||||
pos = argument_str.find_first_not_of (" ", next_token + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (pos != std::string::npos)
|
||||
args.push_back (argument_str.substr (pos, argument_str.length ()));
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
void Commands::AddCommand (const std::string &name, command_cb callback){
|
||||
LogDebug ("Adding Command '%s' at %x", name.c_str(), (void *) callback);
|
||||
|
||||
mCommandsCallbacks[name] = callback;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool Commands::RunCommand (const std::string &command){
|
||||
LogDebug ("Running Command: %s", command.c_str());
|
||||
|
||||
std::string cmd_name = GetCommandName (command);
|
||||
std::string args;
|
||||
|
||||
if (command.length () > cmd_name.length () + 1)
|
||||
args = command.substr (cmd_name.length () + 1, command.length ());
|
||||
|
||||
if (mCommandsCallbacks.find (cmd_name) != mCommandsCallbacks.end()) {
|
||||
std::vector<std::string> argv = ParseArgs (args);
|
||||
if (mCommandsCallbacks[cmd_name] (argv)) {
|
||||
mErrorString = "";
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LogWarning ("Command '%s' not registered!", cmd_name.c_str ());
|
||||
}
|
||||
|
||||
SetErrorString ("Command '" + cmd_name + "' does not exist!");
|
||||
return false;
|
||||
}
|
||||
|
||||
void Commands::QueueCommand (const std::string &command){
|
||||
mCommandQueue.push (command);
|
||||
}
|
||||
|
||||
bool Commands::QueueExecute (){
|
||||
bool result = true;
|
||||
|
||||
while (mCommandQueue.size() > 0) {
|
||||
result = RunCommand (mCommandQueue.front());
|
||||
if (!result) {
|
||||
while (!mCommandQueue.empty())
|
||||
mCommandQueue.pop();
|
||||
|
||||
return false;
|
||||
}
|
||||
mCommandQueue.pop();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Commands::SetErrorString (const std::string &error_str){
|
||||
mErrorString = error_str;
|
||||
LogWarning ("Command Error: %s", error_str.c_str ());
|
||||
}
|
||||
|
||||
std::string Commands::GetErrorString (){
|
||||
return mErrorString;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Global functions
|
||||
*/
|
||||
bool CommandsInitialized () {
|
||||
if (!CommandsInstance) {
|
||||
LogError ("Commands System not yet initialized!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddCommand (const std::string &name, command_cb callback){
|
||||
if (!CommandsInitialized ())
|
||||
return;
|
||||
|
||||
CommandsInstance->AddCommand (name, callback);
|
||||
}
|
||||
|
||||
bool RunCommand (const std::string &command){
|
||||
if (!CommandsInitialized ())
|
||||
return false;
|
||||
|
||||
return CommandsInstance->RunCommand (command);
|
||||
}
|
||||
|
||||
void QueueCommand (const std::string &command){
|
||||
if (!CommandsInitialized ())
|
||||
return;
|
||||
|
||||
CommandsInstance->QueueCommand (command);
|
||||
}
|
||||
|
||||
bool CommandQueueExecute (){
|
||||
if (!CommandsInitialized ())
|
||||
return false;
|
||||
|
||||
return CommandsInstance->QueueExecute ();
|
||||
}
|
||||
|
||||
void CommandSetErrorString (const std::string &error_str){
|
||||
if (!CommandsInitialized ())
|
||||
return;
|
||||
|
||||
CommandsInstance->SetErrorString (error_str);
|
||||
}
|
||||
|
||||
std::string CommandGetErrorString (){
|
||||
if (!CommandsInitialized ())
|
||||
return false;
|
||||
|
||||
return CommandsInstance->GetErrorString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Commands of the Command system
|
||||
*/
|
||||
bool Cmd_Exec (const std::vector<std::string> args) {
|
||||
if (!CommandsInitialized())
|
||||
return false;
|
||||
|
||||
if (args.size() != 1) {
|
||||
CommandsInstance->SetErrorString("usage: exec <path_to_file>");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::ifstream exec_file;
|
||||
exec_file.open(args[0].c_str(), std::ios_base::in);
|
||||
|
||||
if (!exec_file) {
|
||||
std::ostringstream error_msg;
|
||||
error_msg << "exec failed: could not open file '"
|
||||
<< args[0] << "'";
|
||||
CommandsInstance->SetErrorString(error_msg.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
int linecounter = 0;
|
||||
while (!exec_file.eof()) {
|
||||
std::string line;
|
||||
getline (exec_file, line);
|
||||
linecounter++;
|
||||
|
||||
trim_command_str (line);
|
||||
|
||||
if (line.size() == 0)
|
||||
continue;
|
||||
|
||||
if (!CommandsInstance->RunCommand (line)) {
|
||||
std::ostringstream error_msg;
|
||||
error_msg << "exec failed running command '" << line
|
||||
<< "' in file " << args[0] << ":" << linecounter << ".";
|
||||
CommandsInstance->SetErrorString (error_msg.str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
exec_file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Commands::OnRegisterCommands () {
|
||||
AddCommand ("exec", Cmd_Exec);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#ifndef _COMMANDS_H
|
||||
#define _COMMANDS_H
|
||||
|
||||
#include "Engine.h"
|
||||
|
||||
namespace Engine {
|
||||
|
||||
class Module;
|
||||
|
||||
/** \brief The callback signature for commands */
|
||||
typedef bool (*command_cb) (std::vector<std::string>);
|
||||
|
||||
/** \brief Contains all the facilities to parse/add/execute/... commands
|
||||
*
|
||||
* \todo make the command system case insensitive
|
||||
*
|
||||
* This system is mainly used for passing instructions to the Model and
|
||||
* modifying it in this way. Commands can be added with a name (string) and a
|
||||
* function (callback). It also contains a CommandQueue to faciliate delayed
|
||||
* execution of commands and also does the parsing of functions passed to it.
|
||||
*
|
||||
* Functions that should be callable by the Commands module must have the
|
||||
* following signature:
|
||||
* \code
|
||||
* bool MyFunc_cmd (std::vector<std::string> args);
|
||||
* \endcode
|
||||
* To keep things readable one is advised to add \c _cmd at the end of the
|
||||
* function so that it is clear that this function is meant to be called by
|
||||
* the Commands module.
|
||||
*
|
||||
* Scope: Globally visible (since commands must be added)
|
||||
*
|
||||
*/
|
||||
class Commands : public Module {
|
||||
public:
|
||||
/** \brief Adds the function callback as command for the given name*/
|
||||
void AddCommand (const std::string &name, command_cb callback);
|
||||
/** \brief Executes the given command immediately */
|
||||
bool RunCommand (const std::string &command);
|
||||
/** \brief Adds the given command to the command queue */
|
||||
void QueueCommand (const std::string &command);
|
||||
/** \brief Executes the command queue */
|
||||
bool QueueExecute ();
|
||||
/** \brief When a command fails it sets the error with this function */
|
||||
void SetErrorString (const std::string &error_str);
|
||||
/** \brief Returns the error string */
|
||||
std::string GetErrorString ();
|
||||
|
||||
protected:
|
||||
/** \brief Initializes the system */
|
||||
virtual int OnInit (int argc, char* argv[]);
|
||||
/** \brief Destroys the system (must be called!) */
|
||||
virtual void OnDestroy ();
|
||||
/** \brief Registers commands relevant to the Command system */
|
||||
virtual void OnRegisterCommands ();
|
||||
|
||||
/** \brief All registered commands are in this map */
|
||||
std::map<std::string, command_cb> mCommandsCallbacks;
|
||||
/** \brief Queue for the commands */
|
||||
std::queue<std::string> mCommandQueue;
|
||||
/** \brief Holds the error message of a failed command */
|
||||
std::string mErrorString;
|
||||
|
||||
private:
|
||||
std::string GetCommandName (const std::string &command);
|
||||
std::vector<std::string> ParseArgs (std::string &argument_str);
|
||||
};
|
||||
|
||||
}
|
||||
#endif // _COMMANDS_H
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef _COMMANDSGLOBAL_H
|
||||
#define _COMMANDSGLOBAL_H
|
||||
|
||||
namespace Engine {
|
||||
|
||||
typedef bool (*command_cb) (std::vector<std::string>);
|
||||
|
||||
/** \brief Adds the function callback as command for the given name*/
|
||||
void AddCommand (const std::string &name, command_cb callback);
|
||||
/** \brief Executes the given command immediately */
|
||||
bool RunCommand (const std::string &command);
|
||||
/** \brief Adds the given command to the command queue */
|
||||
void QueueCommand (const std::string &command);
|
||||
/** \brief Executes the command queue */
|
||||
bool CommandQueueExecute ();
|
||||
/** \brief When a command fails it sets the error with this function */
|
||||
void CommandSetErrorString (const std::string &error_str);
|
||||
/** \brief Returns the error string */
|
||||
std::string CommandGetErrorString ();
|
||||
|
||||
}
|
||||
|
||||
#endif /* _COMMANDSGLOBAL_H */
|
||||
|
||||
@@ -0,0 +1,264 @@
|
||||
#include "ControllerBase.h"
|
||||
|
||||
#include "ModelBase.h"
|
||||
#include "ViewBase.h"
|
||||
#include "CommandsGlobal.h"
|
||||
|
||||
#include "keytable.h"
|
||||
|
||||
namespace Engine {
|
||||
|
||||
static ControllerBase *ControllerInstance = NULL;
|
||||
|
||||
/*
|
||||
* Helper functions
|
||||
*/
|
||||
|
||||
/** \brief Converts the SDL_BUTTON_* to a value we know */
|
||||
MouseButton convert_sdl_button (Uint8 button) {
|
||||
MouseButton mouse_button;
|
||||
switch (button) {
|
||||
case SDL_BUTTON_LEFT:
|
||||
mouse_button = MouseButtonLeft;
|
||||
break;
|
||||
case SDL_BUTTON_MIDDLE:
|
||||
mouse_button = MouseButtonMiddle;
|
||||
break;
|
||||
case SDL_BUTTON_RIGHT:
|
||||
mouse_button = MouseButtonRight;
|
||||
break;
|
||||
case SDL_BUTTON_WHEELUP:
|
||||
mouse_button = MouseButtonWheelUp;
|
||||
break;
|
||||
case SDL_BUTTON_WHEELDOWN:
|
||||
mouse_button = MouseButtonWheelDown;
|
||||
break;
|
||||
default:
|
||||
mouse_button = MouseButtonUnknown;
|
||||
break;
|
||||
}
|
||||
|
||||
return mouse_button;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inherited Module functions
|
||||
*/
|
||||
int ControllerBase::OnInit (int argc, char* argv[]) {
|
||||
LogDebug ("Controller Init");
|
||||
|
||||
// clear all bindings
|
||||
int i;
|
||||
for (i = 0; i < BINDING_KEYS_LAST; i++)
|
||||
mBindings[i] = "";
|
||||
|
||||
ControllerInstance = this;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ControllerBase::OnDestroy () {
|
||||
ControllerInstance = NULL;
|
||||
|
||||
LogDebug ("Controller Destroy");
|
||||
}
|
||||
|
||||
/*
|
||||
* Module specific functions
|
||||
*/
|
||||
bool ControllerBase::BindKey (int key, const char *command) {
|
||||
if (key <= 0 || key >= BINDING_KEYS_LAST) {
|
||||
LogError ("Could not bind to key with index '%d': invalid index!", key);
|
||||
return false;
|
||||
}
|
||||
|
||||
mBindings[key] = command;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ControllerBase::Process () {
|
||||
ProcessEvents ();
|
||||
|
||||
mView->CalcWorldCoordinates (mMouseScreenPosition[0], mMouseScreenPosition[1],
|
||||
0., mMouseWorldPosition);
|
||||
|
||||
/*
|
||||
LogMessage ("Screenpos = %2d,%2d Worldpos = %f,%f,%f",
|
||||
mMouseScreenPosition[0], mMouseScreenPosition[1],
|
||||
mMouseWorldPosition[0], mMouseWorldPosition[1], mMouseWorldPosition[2]);
|
||||
*/
|
||||
}
|
||||
|
||||
void ControllerBase::ProcessEvents () {
|
||||
SDL_Event event;
|
||||
|
||||
while (SDL_PollEvent(&event)) {
|
||||
/* We are only worried about SDL_KEYDOWN and SDL_KEYUP events */
|
||||
switch (event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
OnKeyDown (event.key.keysym);
|
||||
break;
|
||||
|
||||
case SDL_KEYUP:
|
||||
OnKeyUp (event.key.keysym);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEMOTION:
|
||||
OnMouseMotion(event.motion.x, event.motion.y);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
OnMouseButtonDown (event.button.button, event.button.x, event.button.y);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
OnMouseButtonUp (event.button.button, event.button.x, event.button.y);
|
||||
break;
|
||||
|
||||
case SDL_VIDEORESIZE:
|
||||
OnVideoResize (event.resize.w, event.resize.h);
|
||||
break;
|
||||
|
||||
case SDL_QUIT:
|
||||
EngineSetStatus (EngineStatusStopping);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief Keyboard processing */
|
||||
bool ControllerBase::OnKeyDown (const SDL_keysym &keysym) {
|
||||
if (mView->SendKeyDown (keysym))
|
||||
return true;
|
||||
|
||||
if (mBindings[keysym.sym].size () != 0) {
|
||||
QueueCommand (mBindings[keysym.sym]);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \brief Keyboard processing */
|
||||
bool ControllerBase::OnKeyUp (const SDL_keysym &keysym) {
|
||||
if (mView->SendKeyUp (keysym))
|
||||
return true;
|
||||
|
||||
if (mBindings[keysym.sym].size () != 0) {
|
||||
if (mBindings[keysym.sym][0] == '+') {
|
||||
std::string upcommand = mBindings[keysym.sym];
|
||||
upcommand[0] = '-';
|
||||
QueueCommand (upcommand);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \brief Mouse processing */
|
||||
bool ControllerBase::OnMouseButtonDown (Uint8 button, Uint16 xpos, Uint16 ypos) {
|
||||
MouseButton mouse_button = convert_sdl_button (button);
|
||||
|
||||
if (mView->SendMouseButtonDown (button, xpos, ypos))
|
||||
return true;
|
||||
|
||||
if (mBindings[mouse_button].size () != 0) {
|
||||
QueueCommand (mBindings[mouse_button]);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \brief Mouse processing */
|
||||
bool ControllerBase::OnMouseButtonUp (Uint8 button, Uint16 xpos, Uint16 ypos) {
|
||||
MouseButton mouse_button = convert_sdl_button (button);
|
||||
|
||||
if (mView->SendMouseButtonUp (button, xpos, ypos))
|
||||
return true;
|
||||
|
||||
if (mBindings[mouse_button].size () != 0) {
|
||||
if (mBindings[mouse_button][0] == '+') {
|
||||
std::string upcommand = mBindings[mouse_button];
|
||||
upcommand[0] = '-';
|
||||
QueueCommand (upcommand);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \brief Mouse processing */
|
||||
bool ControllerBase::OnMouseMotion (const int xnew, const int ynew) {
|
||||
mMouseScreenPosition[0] = xnew;
|
||||
mMouseScreenPosition[1] = ynew;
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \brief Video */
|
||||
bool ControllerBase::OnVideoResize (int width, int height) {
|
||||
mView->Resize (width, height);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int convert_keystring (const char *key_val) {
|
||||
std::string keystr (key_val);
|
||||
|
||||
// convert the keystr to lowercase
|
||||
for (std::string::iterator iter = keystr.begin(); iter != keystr.end(); iter++)
|
||||
(*iter) = tolower(*iter);
|
||||
|
||||
// now we search through the table for he value we were given
|
||||
int i = 0;
|
||||
while (key_table[i].keynum != keytable_last) {
|
||||
if (keystr.compare(key_table[i].keystr) == 0)
|
||||
return key_table[i].keynum;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Commands for the ControllerBase
|
||||
*/
|
||||
bool Cmd_Bind (const std::vector<std::string> args) {
|
||||
if (ControllerInstance == NULL) {
|
||||
CommandSetErrorString("Could not bind key: Controller not yet initialized!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.size() != 2) {
|
||||
CommandSetErrorString("usage: bind <key> <command>");
|
||||
return false;
|
||||
}
|
||||
|
||||
int key = convert_keystring (args[0].c_str());
|
||||
|
||||
if (key == 0) {
|
||||
std::ostringstream error_msg;
|
||||
error_msg << "bind failed: invalid key '" << args[0] << '"';
|
||||
CommandSetErrorString(error_msg.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ControllerInstance->BindKey (key, args[1].c_str()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ControllerBase::OnRegisterCommands () {
|
||||
AddCommand ("bind", Cmd_Bind);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
#ifndef _CONTROLLERBASE_H
|
||||
#define _CONTROLLERBASE_H
|
||||
|
||||
#include "Engine.h"
|
||||
|
||||
namespace Engine {
|
||||
|
||||
class ModelBase;
|
||||
class Console;
|
||||
class Module;
|
||||
|
||||
/** \brief Defines the number of keys (keyboard + mous) that we can bind to.
|
||||
*
|
||||
* As the keysym enum of SDL has about 320 keys defined and we might have some
|
||||
* more we set this define to 400 which should suffice. See also the file
|
||||
* keytable.h
|
||||
*/
|
||||
#define BINDING_KEYS_LAST 400
|
||||
|
||||
/** \brief Converts a string into the corresponding keycode */
|
||||
int convert_keystring (const char *key_val);
|
||||
|
||||
/** \brief All input is sent here and distributed from here
|
||||
*
|
||||
* Distributes and modifies the Model and indirectly the view by modifying the
|
||||
* camera. It also holds the configuration of the keybindings and sends
|
||||
* commands to the CommandQueue.
|
||||
*/
|
||||
|
||||
class ControllerBase : public Module {
|
||||
public:
|
||||
/** \brief Processes all inputs and performs all the controlling for the
|
||||
* current frame. */
|
||||
void Process ();
|
||||
/** \brief Returns the current mouse position in screen coordinates */
|
||||
void GetMouseScreenPosition (int *pos_out) {
|
||||
pos_out[0] = mMouseScreenPosition[0];
|
||||
pos_out[1] = mMouseScreenPosition[1];
|
||||
}
|
||||
void GetMouseWorldPosition (float *pos_out) {
|
||||
pos_out[0] = mMouseWorldPosition[0];
|
||||
pos_out[1] = mMouseWorldPosition[1];
|
||||
pos_out[2] = mMouseWorldPosition[2];
|
||||
}
|
||||
bool BindKey (int key, const char *command);
|
||||
|
||||
protected:
|
||||
/** \brief Initializes the system */
|
||||
virtual int OnInit (int argc, char* argv[]);
|
||||
/** \brief Destroys the system (must be called!) */
|
||||
virtual void OnDestroy ();
|
||||
/** \brief Registering of the commands of the ControllerBase */
|
||||
virtual void OnRegisterCommands ();
|
||||
|
||||
/** \brief Processes all Events reported by SDL_PollEvent */
|
||||
virtual void ProcessEvents ();
|
||||
|
||||
/** \brief Keyboard processing */
|
||||
bool OnKeyDown (const SDL_keysym &keysym);
|
||||
/** \brief Keyboard processing */
|
||||
bool OnKeyUp (const SDL_keysym &keysym);
|
||||
|
||||
/** \brief Mouse processing */
|
||||
bool OnMouseButtonDown (Uint8 button, Uint16 xpos, Uint16 ypos);
|
||||
/** \brief Mouse processing */
|
||||
bool OnMouseButtonUp (Uint8 button, Uint16 xpos, Uint16 ypos);
|
||||
/** \brief Mouse processing */
|
||||
bool OnMouseMotion (const int xnew, const int ynew);
|
||||
|
||||
/** \brief Resizes the size of the View */
|
||||
bool OnVideoResize (int width, int height);
|
||||
|
||||
/** \brief Needs the Model to modify it */
|
||||
ModelBase * mModel;
|
||||
/** \brief Input might be sent to the Console, hence it is here */
|
||||
Console * mConsole;
|
||||
/** \brief The View which can get modified by Controller */
|
||||
ViewBase *mView;
|
||||
|
||||
/** \brief Stores the current mouse position in screen coordinates */
|
||||
int mMouseScreenPosition[2];
|
||||
/** \brief Stores the current mouse position on the y=0 plane in wolrd * coordinates */
|
||||
float mMouseWorldPosition[3];
|
||||
|
||||
/** \brief Contains all the bindings for the keyboard */
|
||||
std::string mBindings[BINDING_KEYS_LAST];
|
||||
|
||||
friend class Engine;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // _CONTROLLERBASE_H
|
||||
@@ -0,0 +1,247 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "mathlib.h"
|
||||
#include "DrawingsGL.h"
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
||||
static void CubeVertices () {
|
||||
// front
|
||||
glVertex3f (0.5, -0.5, 0.5);
|
||||
glVertex3f (0.5, -0.5, -0.5);
|
||||
glVertex3f (0.5, 0.5, -0.5);
|
||||
glVertex3f (0.5, 0.5, 0.5);
|
||||
// back
|
||||
glVertex3f (-0.5, 0.5, 0.5);
|
||||
glVertex3f (-0.5, 0.5, -0.5);
|
||||
glVertex3f (-0.5, -0.5, -0.5);
|
||||
glVertex3f (-0.5, -0.5, 0.5);
|
||||
// left
|
||||
glVertex3f (-0.5, -0.5, 0.5);
|
||||
glVertex3f (0.5, -0.5, 0.5);
|
||||
glVertex3f (0.5, 0.5, 0.5);
|
||||
glVertex3f (-0.5, 0.5, 0.5);
|
||||
// right
|
||||
glVertex3f (-0.5, 0.5, -0.5);
|
||||
glVertex3f (0.5, 0.5, -0.5);
|
||||
glVertex3f (0.5, -0.5, -0.5);
|
||||
glVertex3f (-0.5, -0.5, -0.5);
|
||||
// bottom
|
||||
glVertex3f (-0.5, -0.5, -0.5);
|
||||
glVertex3f (0.5, -0.5, -0.5);
|
||||
glVertex3f (0.5, -0.5, 0.5);
|
||||
glVertex3f (-0.5, -0.5, 0.5);
|
||||
// top
|
||||
glVertex3f (-0.5, 0.5, 0.5);
|
||||
glVertex3f (0.5, 0.5, 0.5);
|
||||
glVertex3f (0.5, 0.5, -0.5);
|
||||
glVertex3f (-0.5, 0.5, -0.5);
|
||||
}
|
||||
|
||||
void DrawWireCube () {
|
||||
glBegin (GL_LINE_STRIP);
|
||||
CubeVertices ();
|
||||
glEnd ();
|
||||
}
|
||||
|
||||
void DrawSolidCube () {
|
||||
glBegin (GL_QUADS);
|
||||
CubeVertices ();
|
||||
glEnd ();
|
||||
}
|
||||
|
||||
void DrawCircle () {
|
||||
int i, segments;
|
||||
segments = 20;
|
||||
double x, z, rad, drad;
|
||||
|
||||
drad = (M_PI * 2) / segments;
|
||||
|
||||
// Top
|
||||
glBegin (GL_TRIANGLE_FAN);
|
||||
glVertex3f (0., 0.5, 0.);
|
||||
for (i = 0; i <= segments; i++) {
|
||||
rad = drad * i;
|
||||
sincos (rad, &z, &x);
|
||||
glVertex3f (x * 0.5, 0., -z * 0.5);
|
||||
}
|
||||
glEnd ();
|
||||
}
|
||||
|
||||
void DrawTorus () {
|
||||
int i, segments;
|
||||
segments = 20;
|
||||
double x, z, rad, drad;
|
||||
|
||||
drad = (M_PI * 2) / segments;
|
||||
|
||||
// Top
|
||||
glBegin (GL_TRIANGLE_FAN);
|
||||
glVertex3f (0., 0.5, 0.);
|
||||
for (i = 0; i <= segments; i++) {
|
||||
rad = drad * i;
|
||||
sincos (rad, &z, &x);
|
||||
glVertex3f (x * 0.5, 0.5, -z * 0.5);
|
||||
}
|
||||
glEnd ();
|
||||
|
||||
// Bottom
|
||||
glBegin (GL_TRIANGLE_FAN);
|
||||
glVertex3f (0., -0.5, 0.);
|
||||
for (i = 0; i <= segments; i++) {
|
||||
rad = -drad * i;
|
||||
sincos (rad, &z, &x);
|
||||
glVertex3f (x * 0.5, -0.5, -z * 0.5);
|
||||
}
|
||||
glEnd ();
|
||||
|
||||
// Sides
|
||||
glBegin (GL_QUAD_STRIP);
|
||||
for (i = 0; i <= segments; i++) {
|
||||
rad = drad * i;
|
||||
sincos (rad, &z, &x);
|
||||
glVertex3f (x * 0.5, 0.5, -z * 0.5);
|
||||
glVertex3f (x * 0.5, -0.5, -z * 0.5);
|
||||
}
|
||||
glEnd ();
|
||||
}
|
||||
|
||||
void DrawPoint (float r, float x, float y, float z) {
|
||||
glPointSize (r);
|
||||
glBegin (GL_POINTS);
|
||||
glVertex3f (x, y, z);
|
||||
glEnd ();
|
||||
glPointSize (1.);
|
||||
}
|
||||
|
||||
void DrawAxis() {
|
||||
glColor4f(1., 1., 1., 1.);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(0., 0., 0.);
|
||||
glVertex3f(1., 0., 0.);
|
||||
glVertex3f(0., 0., 0.);
|
||||
glVertex3f(0., 1., 0.);
|
||||
glVertex3f(0., 0., 0.);
|
||||
glVertex3f(0., 0., 1.);
|
||||
glEnd();
|
||||
|
||||
// X
|
||||
glPushMatrix();
|
||||
glTranslatef(1., 0., 0.);
|
||||
glColor3f(1., 0., 0.);
|
||||
glScalef(0.2, 0.1, 0.1);
|
||||
DrawCone(10);
|
||||
glTranslatef(0.4, 0., 0.);
|
||||
// glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'x');
|
||||
glPopMatrix();
|
||||
|
||||
// Y
|
||||
glPushMatrix();
|
||||
glTranslatef(0., 1., 0.);
|
||||
glRotatef(90, 0., 0., 1.);
|
||||
glColor3f(0., 1., 0.);
|
||||
glScalef(0.2, 0.1, 0.1);
|
||||
DrawCone(10);
|
||||
glTranslatef(0.4, 0., 0.);
|
||||
// glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'y');
|
||||
glPopMatrix();
|
||||
|
||||
// Z
|
||||
glPushMatrix();
|
||||
glTranslatef(0., 0., 1.);
|
||||
glRotatef(90, 0., -1., 0.);
|
||||
glColor3f(0., 0., 1.);
|
||||
glScalef(0.2, 0.1, 0.1);
|
||||
DrawCone(10);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void DrawDisc(float radius, int segments) {
|
||||
int i;
|
||||
float radiant;
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glVertex3f(0., 0., 0.);
|
||||
for (i = 0; i <= segments; i++) {
|
||||
radiant = (float) i * ((2 * M_PI) / (float) segments);
|
||||
glVertex3f(radius * cos(radiant), 0., radius * sin(radiant));
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void DrawCircle(float radius, int segments) {
|
||||
int i;
|
||||
float radiant;
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3f(0., 0., 0.);
|
||||
for (i = 0; i <= segments; i++) {
|
||||
radiant = (float) i * ((2 * M_PI) / (float) segments);
|
||||
glVertex3f(radius * cos(radiant), 0., radius * sin(radiant));
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void DrawCone(int segments) {
|
||||
int i;
|
||||
float radiant;
|
||||
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glVertex3f(1., 0., 0.);
|
||||
for (i = 0; i <= segments; i++) {
|
||||
radiant = (float) (i * (2. * M_PI) / (float) segments);
|
||||
|
||||
glVertex3f(0., cos(radiant), sin(radiant));
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void DrawVector(vector3d start, vector3d end) {
|
||||
vector3d direction (end - start);
|
||||
|
||||
glColor3f(1., 1., 1.);
|
||||
glLineWidth(2.);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(start[0], start[1], start[2]);
|
||||
glVertex3f(end[0], end[1], end[2]);
|
||||
glEnd();
|
||||
glLineWidth(1.);
|
||||
|
||||
vector3d right;
|
||||
vector3d up;
|
||||
vector3d direction_norm = direction / direction.length();
|
||||
float cone_radius = 0.15;
|
||||
vector3d conebottom = end - direction_norm * 0.3;
|
||||
|
||||
// Draw the tip
|
||||
if (fabs(direction[0]) > fabs(direction[1]) && fabs(direction[2]) > fabs(direction[1])) {
|
||||
up.setValues (0., 1., 0.);
|
||||
vector3d right = direction.cross (up);
|
||||
right = right / right.length();
|
||||
|
||||
int i;
|
||||
int segments = 20.;
|
||||
float rad_delta = 2. * M_PI / (float) segments;
|
||||
double s,c;
|
||||
|
||||
glColor3f(0.2, 0.2, 0.5);
|
||||
glPointSize (10.);
|
||||
glBegin (GL_TRIANGLE_FAN);
|
||||
glVertex3f (end[0], end[1], end[2]);
|
||||
|
||||
for (i = 0; i <= segments; i ++) {
|
||||
sincos (i * rad_delta, &s, &c);
|
||||
glVertex3f (conebottom[0] + right[0] * cone_radius * c, conebottom[1] + s * cone_radius, conebottom[2] + right[2] * cone_radius * c);
|
||||
}
|
||||
|
||||
glEnd ();
|
||||
glBegin (GL_TRIANGLE_FAN);
|
||||
glVertex3f (conebottom[0], conebottom[1], conebottom[2]);
|
||||
for (i = 0; i <= segments; i ++) {
|
||||
sincos (i * rad_delta, &s, &c);
|
||||
glVertex3f (conebottom[0] + right[0] * cone_radius * c, conebottom[1] + s * cone_radius, conebottom[2] + right[2] * cone_radius * c);
|
||||
}
|
||||
|
||||
glEnd ();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef _DRAWINGSGL_H
|
||||
#define _DRAWINGSGL_H
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
struct vector3d;
|
||||
|
||||
void DrawWireCube ();
|
||||
void DrawSolidCube ();
|
||||
void DrawCircle ();
|
||||
void DrawTorus ();
|
||||
void DrawPoint (float r, float x, float y, float z);
|
||||
void DrawAxis();
|
||||
void DrawDisc(float radius, int segments);
|
||||
void DrawCircle(float radius, int segments);
|
||||
void DrawCone(int segments);
|
||||
void DrawVector(vector3d start, vector3d end);
|
||||
|
||||
#endif /* _DRAWINGSGL_H */
|
||||
@@ -0,0 +1,353 @@
|
||||
#include "Engine.h"
|
||||
#include "Logging.h"
|
||||
#include "Variables.h"
|
||||
#include "Commands.h"
|
||||
|
||||
#include "PhysicsBase.h"
|
||||
#include "CameraBase.h"
|
||||
|
||||
#include "ViewBase.h"
|
||||
#include "ModelBase.h"
|
||||
#include "ControllerBase.h"
|
||||
|
||||
#include "EntityFactoryBase.h"
|
||||
#include "EventsBase.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <cstdlib>
|
||||
#include <assert.h>
|
||||
|
||||
int vasprintf (char **result, const char *format, va_list *string) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace Engine {
|
||||
|
||||
/* Globaly visible classes */
|
||||
Engine* EngineInstance = NULL;
|
||||
|
||||
/*
|
||||
* Inherited Module functions
|
||||
*/
|
||||
int Engine::OnInit (int argc, char* argv[]) {
|
||||
EngineInstance = this;
|
||||
mStatus = EngineStatusUndefined;
|
||||
|
||||
/* Initialization of the base modules */
|
||||
if (mLogging == NULL)
|
||||
mLogging = new Logging ();
|
||||
|
||||
if (! mLogging ) {
|
||||
SetError ("Could not allocate memory for Logging!");
|
||||
exit (-1);
|
||||
}
|
||||
mLogging->Init (argc, argv);
|
||||
SetStatus (EngineStatusInitializing);
|
||||
|
||||
if (mEventManager == NULL)
|
||||
mEventManager = new EventManager();
|
||||
|
||||
mEventManager->Init (argc, argv);
|
||||
|
||||
if (mVariables == NULL)
|
||||
mVariables = new Variables ();
|
||||
if (! mVariables ) {
|
||||
SetError ("Could not allocate memory for Variables!");
|
||||
exit (-1);
|
||||
}
|
||||
mVariables->Init (argc, argv);
|
||||
|
||||
if (mCommands == NULL)
|
||||
mCommands = new Commands ();
|
||||
if (! mCommands ) {
|
||||
SetError ("Could not allocate memory for Commands!");
|
||||
exit (-1);
|
||||
}
|
||||
mCommands->Init (argc, argv);
|
||||
|
||||
// Initialize the SDL
|
||||
LogDebug ("Initializing SDL");
|
||||
if ( SDL_Init ( SDL_INIT_VIDEO ) < 0) {
|
||||
LogError ("Error initializing SDL: %s", SDL_GetError ());
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
|
||||
/* Model */
|
||||
if (mModel == NULL)
|
||||
mModel = new ModelBase ();
|
||||
|
||||
if (! mModel ) {
|
||||
SetError ("Could not allocate memory for Model!");
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
/* Initialization of the modules for the model */
|
||||
if (mEntityFactory == NULL)
|
||||
mEntityFactory = new EntityFactoryBase;
|
||||
|
||||
mModel->mEntityFactory = mEntityFactory;
|
||||
|
||||
|
||||
/* Physics */
|
||||
if (mPhysics == NULL) {
|
||||
mPhysics = new PhysicsBase ();
|
||||
|
||||
if (! mPhysics ) {
|
||||
SetError ("Could not allocate memory for Physics!");
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
|
||||
mModel->mPhysics = mPhysics;
|
||||
|
||||
mEntityFactory->Init (argc, argv);
|
||||
mModel->mPhysics->Init (argc, argv);
|
||||
mModel->Init (argc, argv);
|
||||
|
||||
/* View */
|
||||
if (mView == NULL)
|
||||
mView = new ViewBase ();
|
||||
|
||||
if (! mView ) {
|
||||
SetError ("Could not allocate memory for View!");
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
mView->mCamera = new CameraBase ();
|
||||
mView->mCamera->Init (argc, argv);
|
||||
|
||||
mView->mModel = mModel;
|
||||
mView->Init (argc, argv);
|
||||
|
||||
/* Controller */
|
||||
if (mController == NULL)
|
||||
mController = new ControllerBase ();
|
||||
|
||||
if (! mController ) {
|
||||
SetError ("Could not allocate memory for Controller!");
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
mController->mModel = mModel;
|
||||
mController->mView = mView;
|
||||
|
||||
mController->Init (argc, argv);
|
||||
|
||||
/* Now register the commands */
|
||||
mLogging->RegisterCommands ();
|
||||
mVariables->RegisterCommands ();
|
||||
mCommands->RegisterCommands ();
|
||||
|
||||
mModel->mPhysics->RegisterCommands ();
|
||||
mModel->RegisterCommands ();
|
||||
|
||||
mView->mCamera->RegisterCommands ();
|
||||
mView->RegisterCommands ();
|
||||
|
||||
mController->RegisterCommands ();
|
||||
|
||||
RegisterCommands ();
|
||||
|
||||
/* Now we are done */
|
||||
SetStatus (EngineStatusInitialized);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Engine::OnDestroy () {
|
||||
SetStatus (EngineStatusDestroying);
|
||||
|
||||
// Quit the SDL
|
||||
SDL_Quit ();
|
||||
|
||||
if (mController) {
|
||||
mController->Destroy ();
|
||||
delete mController;
|
||||
mController = NULL;
|
||||
}
|
||||
|
||||
if (mView) {
|
||||
if (mView->mCamera ) {
|
||||
mView->mCamera->Destroy ();
|
||||
delete mView->mCamera;
|
||||
}
|
||||
|
||||
mView->Destroy ();
|
||||
delete mView;
|
||||
mView = NULL;
|
||||
}
|
||||
|
||||
if (mModel) {
|
||||
mModel->Destroy ();
|
||||
|
||||
if (mModel->mPhysics ) {
|
||||
mModel->mPhysics->Destroy ();
|
||||
delete mModel->mPhysics;
|
||||
}
|
||||
|
||||
delete mModel;
|
||||
mModel = NULL;
|
||||
}
|
||||
|
||||
if (mCommands) {
|
||||
mCommands->Destroy ();
|
||||
delete mCommands;
|
||||
mCommands = NULL;
|
||||
}
|
||||
|
||||
if (mVariables) {
|
||||
mVariables->Destroy ();
|
||||
delete mVariables;
|
||||
mVariables = NULL;
|
||||
}
|
||||
|
||||
SetStatus (EngineStatusStopped);
|
||||
|
||||
if (mEventManager) {
|
||||
mEventManager->Destroy();
|
||||
delete mEventManager;
|
||||
mEventManager = NULL;
|
||||
}
|
||||
|
||||
if (mLogging) {
|
||||
mLogging->Destroy ();
|
||||
delete mLogging;
|
||||
mLogging = NULL;
|
||||
}
|
||||
|
||||
mStatus = EngineStatusUndefined;
|
||||
EngineInstance = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Module specific functions
|
||||
*/
|
||||
void Engine::SetStatus (EngineStatus new_status) {
|
||||
LogDebug ("EngineStatus Change: '%d' -> '%d'", mStatus, new_status);
|
||||
mStatus = new_status;
|
||||
}
|
||||
|
||||
EngineStatus Engine::GetStatus () {
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
void Engine::OnMainLoop () {
|
||||
SetStatus (EngineStatusRunning);
|
||||
|
||||
while (mStatus == EngineStatusRunning) {
|
||||
mController->Process ();
|
||||
mCommands->QueueExecute ();
|
||||
mEventManager->Process();
|
||||
mModel->UpdateTimer ();
|
||||
mModel->Process ();
|
||||
mView->Draw ();
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::SetError (const char* str, ...) {
|
||||
static char msg[LOG_MAX_MESSAGE_LENGTH];
|
||||
static int last_length = LOG_MAX_MESSAGE_LENGTH;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < last_length; i++)
|
||||
msg[i] = 0;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
vsprintf(msg, str, ap);
|
||||
va_end(ap);
|
||||
|
||||
mErrorString = msg;
|
||||
|
||||
last_length = strlen (msg);
|
||||
}
|
||||
|
||||
const char* Engine::GetError () {
|
||||
return mErrorString.c_str();
|
||||
}
|
||||
|
||||
/*
|
||||
* Global functions
|
||||
*/
|
||||
void EngineSetError (const char* str, ...) {
|
||||
if (EngineInstance == NULL) {
|
||||
std::cerr << "Error: Engine Instance not yet initialized!" << std::endl;
|
||||
assert (0);
|
||||
}
|
||||
|
||||
static char msg[LOG_MAX_MESSAGE_LENGTH];
|
||||
static int last_length = LOG_MAX_MESSAGE_LENGTH;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < last_length; i++)
|
||||
msg[i] = 0;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
vsprintf(msg, str, ap);
|
||||
va_end(ap);
|
||||
|
||||
EngineInstance->SetError (msg);
|
||||
|
||||
last_length = strlen (msg);
|
||||
}
|
||||
|
||||
const char* EngineGetError () {
|
||||
if (EngineInstance == NULL) {
|
||||
std::cerr << "Error: Engine Instance not yet initialized!" << std::endl;
|
||||
assert (0);
|
||||
}
|
||||
|
||||
return EngineInstance->GetError ();
|
||||
}
|
||||
|
||||
void EngineSetStatus (const EngineStatus status) {
|
||||
if (EngineInstance == NULL) {
|
||||
std::cerr << "Error: Engine Instance not yet initialized!" << std::endl;
|
||||
assert (0);
|
||||
}
|
||||
|
||||
EngineInstance->SetStatus (status);
|
||||
}
|
||||
|
||||
EngineStatus EngineGetStatus () {
|
||||
if (EngineInstance == NULL) {
|
||||
std::cerr << "Error: Engine Instance not yet initialized!" << std::endl;
|
||||
assert (0);
|
||||
}
|
||||
|
||||
return EngineInstance->GetStatus ();
|
||||
}
|
||||
|
||||
ModelBase* EngineGetModel () {
|
||||
if (EngineInstance == NULL) {
|
||||
std::cerr << "Error: Engine Instance not yet initialized!" << std::endl;
|
||||
assert (0);
|
||||
}
|
||||
|
||||
return EngineInstance->GetModel();
|
||||
}
|
||||
|
||||
ViewBase* EngineGetView () {
|
||||
if (EngineInstance == NULL) {
|
||||
std::cerr << "Error: Engine Instance not yet initialized!" << std::endl;
|
||||
assert (0);
|
||||
}
|
||||
|
||||
return EngineInstance->GetView();
|
||||
}
|
||||
|
||||
ControllerBase* EngineGetController () {
|
||||
if (EngineInstance == NULL) {
|
||||
std::cerr << "Error: Engine Instance not yet initialized!" << std::endl;
|
||||
assert (0);
|
||||
}
|
||||
|
||||
return EngineInstance->GetController();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
#ifndef _ENGINE_H
|
||||
#define _ENGINE_H
|
||||
|
||||
#include <globals.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <bitset>
|
||||
|
||||
#include "Module.h"
|
||||
|
||||
// Some ugly #defines
|
||||
|
||||
/** \brief Defines the number of keys that can be defined for an EntityController
|
||||
*
|
||||
* The current state of the controls for an entity is stored in an std::bitset
|
||||
* and each bit tells us whether the key is pressed or not. Unfortunately we
|
||||
* have to know the number of bits that are to be reserved in advance so this
|
||||
* is hard coded into the library for now.
|
||||
*/
|
||||
#define ENTITY_CONTROLLER_MAX_KEY_STATES 64
|
||||
|
||||
namespace Engine {
|
||||
|
||||
class ModelBase;
|
||||
class ViewBase;
|
||||
class ControllerBase;
|
||||
class PhysicsBase;
|
||||
class EntityFactoryBase;
|
||||
class EventManager;
|
||||
|
||||
class Logging;
|
||||
class Commands;
|
||||
class Variables;
|
||||
class Variable;
|
||||
|
||||
enum EngineStatus {
|
||||
EngineStatusUndefined = 0,
|
||||
EngineStatusInitializing,
|
||||
EngineStatusInitialized,
|
||||
EngineStatusRunning,
|
||||
EngineStatusStopping,
|
||||
EngineStatusStopped,
|
||||
EngineStatusDestroying
|
||||
};
|
||||
|
||||
/** \brief The outermost class which contains just everything!
|
||||
*
|
||||
* Engine::Engine takes care of initializing, running and destroying the whole
|
||||
* Engine.
|
||||
*
|
||||
* When Initialize called, the submodules are created by Engine and
|
||||
* initializes them. There are two initialization phases:
|
||||
* - Basemodules initialization:
|
||||
* The first phase creates the base modules such as Engine::Logging,
|
||||
* Engine::Variables and Engine::Commands and calls Initialize () on them.
|
||||
* - ModelViewController initialization:
|
||||
* In the second phase at first the Submodules for each Engine::ModelBase, Engine::ViewBase and
|
||||
* Engine::ControllerBase are allocated an initialized. Then the Engine::ModelBase,
|
||||
* Engine::View and Engine::ControllerBase Modules are initialized.
|
||||
*/
|
||||
class Engine : public Module {
|
||||
public:
|
||||
Engine () {
|
||||
mModel = NULL;
|
||||
mView = NULL;
|
||||
mController = NULL;
|
||||
mLogging = NULL;
|
||||
mCommands = NULL;
|
||||
mVariables = NULL;
|
||||
mEntityFactory = NULL;
|
||||
mEventManager = NULL;
|
||||
}
|
||||
|
||||
virtual void MainLoop () {
|
||||
OnMainLoop ();
|
||||
}
|
||||
|
||||
void SetModel (ModelBase *model) { mModel = model; };
|
||||
ModelBase* GetModel () { return mModel; };
|
||||
void SetView (ViewBase *view) { mView = view; };
|
||||
ViewBase* GetView () { return mView; };
|
||||
void SetPhysics (PhysicsBase *physics) { mPhysics = physics; };
|
||||
PhysicsBase* GetPhysics () { return mPhysics; };
|
||||
void SetEntityFactory (EntityFactoryBase *entityfactory) { mEntityFactory = entityfactory; };
|
||||
|
||||
void SetController (ControllerBase *controller) { mController = controller; };
|
||||
ControllerBase* GetController () { return mController; };
|
||||
void SetLogging (Logging *logging) { mLogging = logging; };
|
||||
void SetCommands (Commands *commands) { mCommands = commands; };
|
||||
void SetVariables (Variables *variables) { mVariables = variables; };
|
||||
|
||||
void SetError (const char* str, ...);
|
||||
const char* GetError ();
|
||||
void SetStatus (const EngineStatus new_status);
|
||||
EngineStatus GetStatus ();
|
||||
|
||||
private:
|
||||
// Engine must not be created with the standard constructor!
|
||||
// It must be ensured, that the correct EntityFactory is used!
|
||||
protected:
|
||||
virtual int OnInit (int argc, char* argv[]);
|
||||
virtual void OnDestroy ();
|
||||
virtual void OnRegisterCommands ();
|
||||
|
||||
void OnMainLoop ();
|
||||
|
||||
ModelBase *mModel;
|
||||
ViewBase *mView;
|
||||
ControllerBase *mController;
|
||||
PhysicsBase *mPhysics;
|
||||
EntityFactoryBase *mEntityFactory;
|
||||
EventManager *mEventManager;
|
||||
|
||||
Logging *mLogging;
|
||||
Commands *mCommands;
|
||||
Variables *mVariables;
|
||||
|
||||
std::string mErrorString;
|
||||
EngineStatus mStatus;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Global visible functions and classes
|
||||
*/
|
||||
|
||||
namespace Engine {
|
||||
/* Globaly visible classes */
|
||||
extern Engine* EngineInstance;
|
||||
|
||||
/** \brief Sets the Engine::mErrorString to the given message */
|
||||
void EngineSetError (const char* str, ...);
|
||||
/** \brief Returns Engine::mErrorString */
|
||||
const char* EngineGetError ();
|
||||
|
||||
/** \brief Sets the current state of the Engine */
|
||||
void EngineSetStatus (const EngineStatus status);
|
||||
/** \brief Returns the current state of the Engine */
|
||||
EngineStatus EngineGetStatus ();
|
||||
|
||||
/** \brief Global access functions for the Model */
|
||||
ModelBase* EngineGetModel ();
|
||||
/** \brief Global access functions for the View */
|
||||
ViewBase* EngineGetView ();
|
||||
/** \brief Global access functions for the Controller */
|
||||
ControllerBase* EngineGetController ();
|
||||
|
||||
}
|
||||
|
||||
/* Include the globally visible declarations of the other modules */
|
||||
#include "LoggingGlobal.h"
|
||||
#include "VariablesGlobal.h"
|
||||
#include "CommandsGlobal.h"
|
||||
#include "ModelBaseGlobal.h"
|
||||
#include "ViewBaseGlobal.h"
|
||||
#include "EventsBaseGlobal.h"
|
||||
|
||||
#endif // _ENGINE_H
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "Engine.h"
|
||||
|
||||
namespace Engine {
|
||||
|
||||
bool Cmd_EngineQuit (std::vector<std::string> args) {
|
||||
EngineSetStatus (EngineStatusStopping);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Engine::OnRegisterCommands () {
|
||||
AddCommand ("quit", Cmd_EngineQuit);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "EntityBase.h"
|
||||
|
||||
#include "coll2d.h"
|
||||
|
||||
namespace Engine {
|
||||
|
||||
bool EntityControllerState::GetKey (int state) {
|
||||
assert (state < ENTITY_CONTROLLER_MAX_KEY_STATES && state >= 0);
|
||||
|
||||
return mKeyState.test (state);
|
||||
}
|
||||
|
||||
void EntityControllerState::SetKey (int state) {
|
||||
assert (state < ENTITY_CONTROLLER_MAX_KEY_STATES && state >= 0);
|
||||
|
||||
LogDebug ("Setting Entity Key State %d", state);
|
||||
mKeyState.set (state);
|
||||
}
|
||||
|
||||
void EntityControllerState::UnsetKey (int state) {
|
||||
assert (state < ENTITY_CONTROLLER_MAX_KEY_STATES && state >= 0);
|
||||
|
||||
LogDebug ("Unsetting Entity Key State %d", state);
|
||||
mKeyState.reset (state);
|
||||
}
|
||||
|
||||
void EntityBase::SetControllerKeyState (int state) {
|
||||
if (!mControllerState) {
|
||||
LogError ("Error when trying to send a KeyState to an Entity that has no EntityControllerState!");
|
||||
assert (0);
|
||||
}
|
||||
|
||||
mControllerState->SetKey (state);
|
||||
}
|
||||
|
||||
void EntityBase::UnsetControllerKeyState (int state) {
|
||||
if (!mControllerState) {
|
||||
LogError ("Error when trying to send a KeyState to an Entity that has no EntityControllerState!");
|
||||
assert (0);
|
||||
}
|
||||
|
||||
mControllerState->UnsetKey (state);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
#ifndef _ENTITYBASE_H
|
||||
#define _ENTITYBASE_H
|
||||
|
||||
#include "Engine.h"
|
||||
#include "mathlib.h"
|
||||
|
||||
#include "EntityBaseTypes.h"
|
||||
|
||||
namespace coll2d {
|
||||
class Shape;
|
||||
}
|
||||
|
||||
namespace Engine {
|
||||
|
||||
/** \brief Contains all the information for the physical simulation of the
|
||||
* Entity
|
||||
*
|
||||
* Every Engine::Entity that should be simulated in the Engine::Physics module
|
||||
* must have a Engine::EntityPhysicState counterpart. It represents the state
|
||||
* of the Entity in the physical world of the engine.
|
||||
*
|
||||
* The Copy-Constructor and Assignment Operator is defined in EntityPhysics.cc
|
||||
* as they require a call to coll2d::Shape::getCopy() which again requires the
|
||||
* inclusion of coll2d.h which should stay out of Entity.h for faster
|
||||
* compilation.
|
||||
*/
|
||||
struct EntityPhysicState {
|
||||
/** \brief Standard constructor */
|
||||
EntityPhysicState ():
|
||||
mId (0),
|
||||
mBaseType (EntityBaseTypeNone),
|
||||
mPosition (0., 0., 0.),
|
||||
mOrientation (0., 0., 0.),
|
||||
mVelocity (0., 0., 0.),
|
||||
mAngleVelocity (0.),
|
||||
mRadius (0.),
|
||||
mShape (NULL),
|
||||
mStatic (false),
|
||||
mAlive (true),
|
||||
mContactNormals() {};
|
||||
|
||||
virtual ~EntityPhysicState() {};
|
||||
|
||||
/** \brief Copy constructor */
|
||||
EntityPhysicState (const EntityPhysicState& state);
|
||||
|
||||
/** \brief Assignment operator */
|
||||
EntityPhysicState& operator= (const EntityPhysicState& state);
|
||||
|
||||
unsigned int mId;
|
||||
/** \brief The type from the game's perspective */
|
||||
int mType;
|
||||
/** \brief The type from the engine's perspective */
|
||||
EntityBaseType mBaseType;
|
||||
|
||||
vector3d mPosition;
|
||||
vector3d mOrientation;
|
||||
vector3d mVelocity;
|
||||
float mAngleVelocity;
|
||||
float mRadius;
|
||||
|
||||
coll2d::Shape* mShape;
|
||||
bool mStatic;
|
||||
|
||||
/** \brief If false, the entity will be removed at the end of the frame. */
|
||||
bool mAlive;
|
||||
|
||||
vector3d &GetPosition ();
|
||||
vector3d &GetVelocity ();
|
||||
vector3d &GetOrientation ();
|
||||
float &GetAngleVelocity ();
|
||||
|
||||
void SetPosition (const vector3d &position);
|
||||
void SetVelocity (const vector3d &velocity);
|
||||
void SetOrientation (const vector3d &orientation);
|
||||
void SetAngleVelocity (const float &angle_velocity);
|
||||
|
||||
/** \brief Transforms the given vector in local space to world coordinates */
|
||||
void Globalize (vector3d &vec);
|
||||
/** \brief Transforms the given vector from world coordinates to local
|
||||
* coordinates */
|
||||
void Localize (vector3d &vec);
|
||||
/** \brief Performs only the rotational part of Globalize() */
|
||||
void GlobalizeRotation (vector3d &vec);
|
||||
/** \brief Performs only the rotational part of Localize() */
|
||||
void LocalizeRotation (vector3d &vec);
|
||||
|
||||
/** \brief Updates the shape for collision detection */
|
||||
void UpdateShape ();
|
||||
|
||||
/** \brief Contains all the normal vectors of the planes with which we are in contact. */
|
||||
std::map<unsigned int, vector3d> mContactNormals;
|
||||
};
|
||||
|
||||
/** \brief Represents the current state of the Entity controller
|
||||
*
|
||||
* This struct stores the current state for all EntityControllerKeyStates
|
||||
* (e.g. whether the keys are currently pressed or not).
|
||||
*
|
||||
* \todo [Low] The current design is very unflexible. Is there a better way?
|
||||
*/
|
||||
struct EntityControllerState {
|
||||
std::bitset<ENTITY_CONTROLLER_MAX_KEY_STATES> mKeyState;
|
||||
|
||||
bool GetKey (int state);
|
||||
void SetKey (int state);
|
||||
void UnsetKey (int state);
|
||||
};
|
||||
|
||||
/** \brief Represents the base of everything that exists in the engine
|
||||
*
|
||||
* An Engine::Entity has different representations in the different
|
||||
* submodules. Engine::EntityPhysicState stores the physical representation of
|
||||
* the entity like its position, velocity, orientation, and shape.
|
||||
* Engine::EntityVisualState is used for drawing an Entity by Engine::View.
|
||||
*/
|
||||
struct EntityBase {
|
||||
unsigned int mId;
|
||||
/** \brief The type from the game's perspective */
|
||||
int mType;
|
||||
/** \brief The type from the engine's perspective */
|
||||
EntityBaseType mBaseType;
|
||||
|
||||
EntityPhysicState *mPhysicState;
|
||||
EntityControllerState *mControllerState;
|
||||
|
||||
/** \brief Applies the state of the EntityControllerState to the EntityPhysicState etc. */
|
||||
virtual void Update (float delta_sec) {};
|
||||
|
||||
/** \brief Adds the given state to the current movement state of the Entity */
|
||||
virtual void SetControllerKeyState (int state);
|
||||
/** \brief Removes the given state to the current movement state of the Entity */
|
||||
virtual void UnsetControllerKeyState (int state);
|
||||
|
||||
/** \brief Helper function to set the id to all substates */
|
||||
void SetId (unsigned int id) {
|
||||
mId = id;
|
||||
|
||||
if (mPhysicState)
|
||||
mPhysicState->mId = id;
|
||||
}
|
||||
|
||||
/** Executes game logic for the collision event
|
||||
* \returns true if it was able to react for this type of entity, false
|
||||
* false otherwise
|
||||
*/
|
||||
virtual bool CollisionEvent (EntityBase* entity_state) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _ENTITYBASE_H
|
||||
@@ -0,0 +1,59 @@
|
||||
#ifndef _ENTITYBASETYPES_H
|
||||
#define _ENTITYBASETYPES_H
|
||||
|
||||
namespace Engine {
|
||||
|
||||
struct EntityBase;
|
||||
struct EntityPhysicState;
|
||||
struct EntityControllerState;
|
||||
|
||||
/** \brief Represents the different types of an entity from the Engines' perspective
|
||||
*
|
||||
* The different EntityBaseTypes define their basic behaviour when it comes to
|
||||
* events such as collisions between two Entities.
|
||||
*
|
||||
* Here is an overview how collisions are handled:
|
||||
*
|
||||
* <table>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td>EntityBaseTypeParticle</td>
|
||||
* <td>EntityBaseTypeBlock</td>
|
||||
* <td>EntityBaseTypeActor</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>EntityBaseTypeParticle</td>
|
||||
* <td>-</td>
|
||||
* <td>C</td>
|
||||
* <td>C</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>EntityBaseTypeBlock</td>
|
||||
* <td>C</td>
|
||||
* <td>C</td>
|
||||
* <td>C</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>EntityBaseTypeActor</td>
|
||||
* <td>C</td>
|
||||
* <td>C</td>
|
||||
* <td>C</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* A 'C' means that Engine::Physics::CheckPossibleCollisionPair() will return
|
||||
* true (this results that the two types cannot penetrate each other).
|
||||
*/
|
||||
enum EntityBaseType {
|
||||
EntityBaseTypeNone = 0, /**< is the default type and does not collide with anything */
|
||||
EntityBaseTypeBlock, /**< represents walls etc. that block Particles, Actors and other Blocks */
|
||||
EntityBaseTypeParticle, /**< is used for projectiles or Entities that just move
|
||||
but are "dumb" apart from that */
|
||||
EntityBaseTypeActor, /**< is the type for objects that interact with each other */
|
||||
EntityBaseTypeLast /**< marks the maximum number of EntityBaseType */
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // _ENTITYBASETYPES_H
|
||||
@@ -0,0 +1,117 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "EntityFactoryBase.h"
|
||||
|
||||
#include "EntityBase.h"
|
||||
#include "coll2d.h"
|
||||
|
||||
namespace Engine {
|
||||
|
||||
int EntityFactoryBase::OnInit (int argc, char* argv[]) {
|
||||
LogMessage ("Initializing EntityFactory");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EntityPhysicState* EntityFactoryBase::CreateEntityPhysicState (int type) {
|
||||
// In this simple factory the type is simply seen as the EntityBaseType.
|
||||
// However to prevent errors we do a simple check vor validity.
|
||||
if (type < 0 || type >> EntityBaseTypeLast ) {
|
||||
LogError ("Cannot create Entity with type %d: invalid type!", type);
|
||||
assert (0);
|
||||
}
|
||||
EntityBaseType base_type = (EntityBaseType) type;
|
||||
|
||||
// Create the Entity
|
||||
EntityPhysicState* entity_physics = new EntityPhysicState ();
|
||||
if (!entity_physics) {
|
||||
LogError ("Could not allocate enough memory for EntityPhysicState of type '%d'", type);
|
||||
assert (0);
|
||||
}
|
||||
|
||||
// default values for all entities
|
||||
entity_physics->mBaseType = base_type;
|
||||
|
||||
// specific values for each Entity base_type
|
||||
if (base_type == EntityBaseTypeNone) {
|
||||
entity_physics->mShape = new coll2d::Sphere (0.01);
|
||||
assert (entity_physics->mShape);
|
||||
} else if (base_type == EntityBaseTypeActor) {
|
||||
entity_physics->mShape = new coll2d::Sphere (0.4);
|
||||
assert (entity_physics->mShape);
|
||||
} else if (base_type == EntityBaseTypeBlock) {
|
||||
entity_physics->mShape = new coll2d::Polygon (4);
|
||||
assert (entity_physics->mShape);
|
||||
|
||||
static_cast<coll2d::Polygon*> (entity_physics->mShape)->setVertice (0, vector3d (-0.5, 0., 0.5));
|
||||
static_cast<coll2d::Polygon*> (entity_physics->mShape)->setVertice (1, vector3d (0.5, 0., 0.5));
|
||||
static_cast<coll2d::Polygon*> (entity_physics->mShape)->setVertice (2, vector3d (0.5, 0., -0.5));
|
||||
static_cast<coll2d::Polygon*> (entity_physics->mShape)->setVertice (3, vector3d (-0.5, 0., -0.5));
|
||||
} else if (base_type == EntityBaseTypeParticle) {
|
||||
entity_physics->mShape = new coll2d::Sphere (0.05);
|
||||
assert (entity_physics->mShape);
|
||||
} else {
|
||||
LogError ("No EntityPhysicState defined for Entity base_type '%d'", base_type);
|
||||
assert (0);
|
||||
}
|
||||
|
||||
return entity_physics;
|
||||
}
|
||||
|
||||
EntityControllerState* EntityFactoryBase::CreateEntityControllerState (int type) {
|
||||
// In this simple factory the type is simply seen as the EntityBaseType.
|
||||
// However to prevent errors we do a simple check vor validity.
|
||||
if (type < 0 || type >> EntityBaseTypeLast ) {
|
||||
LogError ("Cannot create Entity with type %d: invalid type!", type);
|
||||
assert (0);
|
||||
}
|
||||
EntityBaseType base_type = (EntityBaseType) type;
|
||||
|
||||
// Create the Entity
|
||||
EntityControllerState* entity_controller = NULL;
|
||||
|
||||
// specific values for each Entity base_type
|
||||
if (base_type == EntityBaseTypeNone) {
|
||||
} else if (base_type == EntityBaseTypeActor) {
|
||||
entity_controller = new EntityControllerState ();
|
||||
if (!entity_controller) {
|
||||
LogError ("Could not allocate enough memory for EntityControllerState of type '%d'", type);
|
||||
assert (0);
|
||||
}
|
||||
} else if (base_type == EntityBaseTypeBlock) {
|
||||
} else if (base_type == EntityBaseTypeParticle) {
|
||||
} else {
|
||||
LogError ("No EntityPhysicState defined for Entity base_type '%d'", base_type);
|
||||
assert (0);
|
||||
}
|
||||
|
||||
return entity_controller;
|
||||
}
|
||||
|
||||
EntityBase* EntityFactoryBase::CreateEntity (int type) {
|
||||
// In this simple factory the type is simply seen as the EntityBaseType.
|
||||
// However to prevent errors we do a simple check vor validity.
|
||||
if (type < 0 || type >> EntityBaseTypeLast ) {
|
||||
LogError ("Cannot create Entity with type %d: invalid type!", type);
|
||||
assert (0);
|
||||
}
|
||||
EntityBaseType base_type = (EntityBaseType) type;
|
||||
|
||||
// Create the Entity
|
||||
EntityBase *entity = new EntityBase;
|
||||
entity->mBaseType = base_type;
|
||||
|
||||
if (!entity) {
|
||||
LogError ("Could not allocate enough memory for EntityVisualState of type '%d'", type);
|
||||
assert (0);
|
||||
}
|
||||
|
||||
entity->mPhysicState = CreateEntityPhysicState (type);
|
||||
entity->mControllerState = CreateEntityControllerState (type);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef _ENTITYFACTORYBASE_H
|
||||
#define _ENTITYFACTORYASE_H
|
||||
|
||||
#include "Module.h"
|
||||
|
||||
namespace Engine {
|
||||
|
||||
struct EntityBase;
|
||||
|
||||
struct EntityPhysicState;
|
||||
struct EntityControllerState;
|
||||
|
||||
/** \brief Takes care of the creation of user-defined Entities
|
||||
*
|
||||
* To be able to define custom types of Entities we use a Object Factory for
|
||||
* which the actual CreateEntityXYZState () function can be overloaded with
|
||||
* the creation of custom types.
|
||||
*
|
||||
* The method EntityFactory::CreateEntity() will be called by the
|
||||
* Model::CreateEntity() function which also takes care of registering the
|
||||
* Entity to required submodules.
|
||||
*/
|
||||
class EntityFactoryBase : public Module {
|
||||
public: EntityFactoryBase () {};
|
||||
virtual EntityPhysicState* CreateEntityPhysicState (int type);
|
||||
virtual EntityControllerState* CreateEntityControllerState (int type);
|
||||
|
||||
virtual EntityBase* CreateEntity (int type);
|
||||
|
||||
protected:
|
||||
virtual int OnInit (int argc, char* argv[]);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // _ENTITYFACTORYBASE_H
|
||||
@@ -0,0 +1,21 @@
|
||||
// File name: "EnumToString.h"
|
||||
//
|
||||
// From: http://www.codeproject.com/KB/cpp/C___enums_to_strings.aspx
|
||||
//
|
||||
// Thanks to Marcos F. Cardoso
|
||||
|
||||
#undef DECL_ENUM_ELEMENT
|
||||
#undef BEGIN_ENUM
|
||||
#undef END_ENUM
|
||||
|
||||
#ifndef GENERATE_ENUM_STRINGS
|
||||
#define DECL_ENUM_ELEMENT( element ) element
|
||||
#define BEGIN_ENUM( ENUM_NAME ) typedef enum tag##ENUM_NAME
|
||||
#define END_ENUM( ENUM_NAME ) ENUM_NAME; \
|
||||
const char* GetString##ENUM_NAME(enum tag##ENUM_NAME index);
|
||||
#else
|
||||
#define DECL_ENUM_ELEMENT( element ) #element
|
||||
#define BEGIN_ENUM( ENUM_NAME ) const char* gs_##ENUM_NAME [] =
|
||||
#define END_ENUM( ENUM_NAME ) ; const char* GetString##ENUM_NAME(enum \
|
||||
tag##ENUM_NAME index){ return gs_##ENUM_NAME [index]; }
|
||||
#endif
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "EventsBase.h"
|
||||
#include "Logging.h"
|
||||
|
||||
namespace Engine {
|
||||
|
||||
EventManager* EventManagerInstance = NULL;
|
||||
|
||||
int EventManager::OnInit (int argc, char* argv[]) {
|
||||
EventManagerInstance = this;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EventManager::OnDestroy() {
|
||||
EventManagerInstance = NULL;
|
||||
}
|
||||
|
||||
bool EventManager::RegisterListener (const EventListenerBase *listener, const int event_type) {
|
||||
LogDebug ("Registering Event listener %x for event type %d", listener, event_type);
|
||||
|
||||
mEventTypeListeners[event_type].push_back(listener);
|
||||
return true;
|
||||
}
|
||||
|
||||
void EventManager::Process () {
|
||||
while (mQueuedEvents.size() > 0) {
|
||||
TriggerEvent (mQueuedEvents.front());
|
||||
mQueuedEvents.pop();
|
||||
}
|
||||
}
|
||||
|
||||
bool EventManager::QueueEvent (const EventBasePtr &event) {
|
||||
if (!HasEventTypeListener(event->mEventType))
|
||||
return false;
|
||||
|
||||
mQueuedEvents.push (event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EventManager::TriggerEvent (const EventBasePtr &event) {
|
||||
if (!HasEventTypeListener (event->mEventType))
|
||||
return false;
|
||||
|
||||
std::vector<const EventListenerBase*>::iterator listener_iter = mEventTypeListeners[event->mEventType].begin();
|
||||
for ( ; listener_iter != mEventTypeListeners[event->mEventType].end(); listener_iter++) {
|
||||
if ((*listener_iter)->HandleEvent (event))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Global Functions
|
||||
*/
|
||||
/** \brief Registers a listener to a given event type */
|
||||
bool RegisterListener (const EventListenerBase *listener, const int event_type) {
|
||||
if (!EventManagerInstance) {
|
||||
LogError ("Could not register EventListenerBase: EventManager not initialized!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return EventManagerInstance->RegisterListener (listener, event_type);
|
||||
}
|
||||
|
||||
/** \brief Calls all event listeners to handle the events */
|
||||
bool QueueEvent (const EventBasePtr &event) {
|
||||
if (!EventManagerInstance) {
|
||||
LogError ("Could not queue event: EventManager not initialized!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return EventManagerInstance->QueueEvent (event);
|
||||
}
|
||||
|
||||
/** \brief Calls the listener handlers immediately */
|
||||
bool TriggerEvent (const EventBasePtr &event) {
|
||||
if (!EventManagerInstance) {
|
||||
LogError ("Could not trigger event: EventManager not initialized!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return EventManagerInstance->TriggerEvent (event);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
#ifndef EVENTSBASE_H
|
||||
#define EVENTSBASE_H
|
||||
|
||||
#include "Module.h"
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
/** \brief Contains all information relevant to the Event */
|
||||
struct EventBase {
|
||||
int mEventType;
|
||||
|
||||
/** \brief This might later be used for de-/serializing of the event data */
|
||||
std::string mEventData;
|
||||
float mEventFloat;
|
||||
int mEventInt;
|
||||
unsigned int mEventUnsignedInt;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<EventBase> EventBasePtr;
|
||||
|
||||
/** \brief Takes care of the handling of the Event
|
||||
*
|
||||
* Processing of the Event is done in the EventListenerBase::HandleEvent()
|
||||
* function.
|
||||
*/
|
||||
class EventListenerBase {
|
||||
public:
|
||||
virtual ~EventListenerBase() {};
|
||||
/** \brief Handles the Event */
|
||||
virtual bool HandleEvent (const EventBasePtr &event) const = 0;
|
||||
void just_for_the_vtable() {};
|
||||
|
||||
/** \brief For debugging */
|
||||
std::string mName;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<EventListenerBase> EventListenerPtr;
|
||||
|
||||
/** \brief Keeps track of all the EventListenerBase objects and receives Event notifications.
|
||||
*/
|
||||
class EventManager : public Module {
|
||||
public:
|
||||
virtual ~EventManager() {};
|
||||
|
||||
/** \brief Registers a listener to a given event type */
|
||||
bool RegisterListener (const EventListenerBase *listener, const int event_type);
|
||||
/** \brief Calls all event listeners to handle the events */
|
||||
void Process ();
|
||||
/** \brief Queues the until Process() gets called */
|
||||
bool QueueEvent (const EventBasePtr &event);
|
||||
/** \brief Calls the listener handlers immediately */
|
||||
bool TriggerEvent (const EventBasePtr &event);
|
||||
|
||||
/** \brief Returns true if there is a listener for a given event type */
|
||||
bool HasEventTypeListener (const int event_type) {
|
||||
return mEventTypeListeners.find(event_type) != mEventTypeListeners.end();
|
||||
}
|
||||
/** \brief Returns the number of listeners for a given event type */
|
||||
unsigned int GetEventTypeListenerCount (const int event_type) {
|
||||
if (!HasEventTypeListener (event_type))
|
||||
return 0;
|
||||
|
||||
return (mEventTypeListeners.find(event_type))->second.size();
|
||||
}
|
||||
unsigned int GetQueuedEventCount () {
|
||||
return mQueuedEvents.size();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual int OnInit (int argc, char* argv[]);
|
||||
virtual void OnDestroy();
|
||||
|
||||
private:
|
||||
/** \brief Contains for each event type the list of listeners */
|
||||
std::map <int, std::vector<const EventListenerBase*> > mEventTypeListeners;
|
||||
std::queue <EventBasePtr> mQueuedEvents;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* EVENTSBASE_H */
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef EVENTSBASEGLOBAL_H
|
||||
#define EVENTSBASEGLOBAL_H
|
||||
|
||||
#include "EventsBase.h"
|
||||
|
||||
namespace Engine {
|
||||
|
||||
/** \brief Registers a listener to a given event type */
|
||||
bool RegisterListener (const EventListenerBase *listener, const int event_type);
|
||||
/** \brief Calls all event listeners to handle the events */
|
||||
bool QueueEvent (const EventBasePtr &event);
|
||||
/** \brief Calls the listener handlers immediately */
|
||||
bool TriggerEvent (const EventBasePtr &event);
|
||||
|
||||
}
|
||||
#endif /* EVENTSBASEGLOBAL_H */
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "EntityBase.h"
|
||||
#include "ModelBase.h"
|
||||
|
||||
namespace Engine {
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
#include "Logging.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdarg>
|
||||
#include <cstdlib>
|
||||
#include <assert.h>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
static Logging *LoggingInstance = NULL;
|
||||
static LogLevel requested_level = LOG_DEFAULT_LEVEL;
|
||||
|
||||
/*
|
||||
* Inherited Module functions
|
||||
*/
|
||||
int Logging::OnInit (int argc, char* argv[]) {
|
||||
mPrintLevel = requested_level;
|
||||
|
||||
Log (LogLevelDebug, "Logging Init");
|
||||
LoggingInstance = this;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Logging::OnDestroy () {
|
||||
Log (LogLevelDebug, "Logging Destroy");
|
||||
|
||||
LoggingInstance = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Module specific functions
|
||||
*/
|
||||
void Logging::Log (LogLevel level, const char *str, ...) {
|
||||
if (level < mPrintLevel)
|
||||
return;
|
||||
|
||||
static char msg[LOG_MAX_MESSAGE_LENGTH];
|
||||
static int last_length = LOG_MAX_MESSAGE_LENGTH;
|
||||
static int i;
|
||||
|
||||
for (i = 0; i < last_length; i++)
|
||||
msg[i] = 0;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
vsprintf(msg, str, ap);
|
||||
va_end(ap);
|
||||
|
||||
last_length = strlen (msg);
|
||||
assert (last_length < LOG_MAX_MESSAGE_LENGTH);
|
||||
|
||||
std::cout << msg << std::endl;
|
||||
|
||||
LogEntry log_entry (level, msg);
|
||||
mLogEntries.push_back (log_entry);
|
||||
}
|
||||
|
||||
void Logging::SetLogPrintLevel (LogLevel print_level) {
|
||||
mPrintLevel = print_level;
|
||||
}
|
||||
|
||||
const LogEntry &Logging::GetLastEntry () {
|
||||
static LogEntry null_message (LogLevelMessage, "");
|
||||
|
||||
if (mLogEntries.size() > 0) {
|
||||
return mLogEntries[mLogEntries.size() - 1];
|
||||
}
|
||||
|
||||
return null_message;
|
||||
}
|
||||
|
||||
/*
|
||||
* Globally visible functions
|
||||
*/
|
||||
void SetLogPrintLevel (LogLevel print_level) {
|
||||
if (!LoggingInstance) {
|
||||
requested_level = print_level;
|
||||
return;
|
||||
}
|
||||
|
||||
LoggingInstance->SetLogPrintLevel (print_level);
|
||||
}
|
||||
|
||||
void LogError (const char* str, ...) {
|
||||
assert (LoggingInstance);
|
||||
|
||||
static char msg[LOG_MAX_MESSAGE_LENGTH];
|
||||
static int last_length = LOG_MAX_MESSAGE_LENGTH;
|
||||
static int i;
|
||||
|
||||
for (i = 0; i < last_length; i++)
|
||||
msg[i] = 0;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
vsprintf(msg, str, ap);
|
||||
va_end(ap);
|
||||
|
||||
last_length = strlen (msg);
|
||||
assert (last_length < LOG_MAX_MESSAGE_LENGTH);
|
||||
|
||||
LoggingInstance->Log (LogLevelError, msg);
|
||||
}
|
||||
|
||||
void LogWarning (const char* str, ...) {
|
||||
assert (LoggingInstance);
|
||||
|
||||
static char msg[LOG_MAX_MESSAGE_LENGTH];
|
||||
static int last_length = LOG_MAX_MESSAGE_LENGTH;
|
||||
static int i;
|
||||
|
||||
for (i = 0; i < last_length; i++)
|
||||
msg[i] = 0;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
vsprintf(msg, str, ap);
|
||||
va_end(ap);
|
||||
|
||||
last_length = strlen (msg);
|
||||
assert (last_length < LOG_MAX_MESSAGE_LENGTH);
|
||||
|
||||
LoggingInstance->Log (LogLevelWarning, msg);
|
||||
}
|
||||
|
||||
void LogMessage (const char* str, ...) {
|
||||
assert (LoggingInstance);
|
||||
|
||||
static char msg[LOG_MAX_MESSAGE_LENGTH];
|
||||
static int last_length = LOG_MAX_MESSAGE_LENGTH;
|
||||
static int i;
|
||||
|
||||
for (i = 0; i < last_length; i++)
|
||||
msg[i] = 0;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
vsprintf(msg, str, ap);
|
||||
va_end(ap);
|
||||
|
||||
last_length = strlen (msg);
|
||||
assert (last_length < LOG_MAX_MESSAGE_LENGTH);
|
||||
|
||||
LoggingInstance->Log (LogLevelMessage, msg);
|
||||
}
|
||||
|
||||
void LogDebug (const char* str, ...) {
|
||||
assert (LoggingInstance);
|
||||
static char msg[LOG_MAX_MESSAGE_LENGTH];
|
||||
static int last_length = LOG_MAX_MESSAGE_LENGTH;
|
||||
static int i;
|
||||
|
||||
for (i = 0; i < last_length; i++)
|
||||
msg[i] = 0;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
vsprintf(msg, str, ap);
|
||||
va_end(ap);
|
||||
|
||||
last_length = strlen (msg);
|
||||
assert (last_length < LOG_MAX_MESSAGE_LENGTH);
|
||||
|
||||
LoggingInstance->Log (LogLevelDebug, msg);
|
||||
}
|
||||
|
||||
const LogEntry& GetLastLogEntry () {
|
||||
assert (LoggingInstance);
|
||||
return LoggingInstance->GetLastEntry ();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef _LOGGING_H
|
||||
#define _LOGGING_H
|
||||
|
||||
#include "Engine.h"
|
||||
|
||||
namespace Engine {
|
||||
class Module;
|
||||
|
||||
/** \brief All logging goes through this class
|
||||
*/
|
||||
class Logging : public Module {
|
||||
public:
|
||||
void Log (LogLevel level, const char *str, ...);
|
||||
void SetLogPrintLevel (LogLevel print_level);
|
||||
/** \brief Returns the last LogEntry that was sent to the Logging module
|
||||
*/
|
||||
const LogEntry& GetLastEntry ();
|
||||
|
||||
protected:
|
||||
/** \brief Initializes the system */
|
||||
virtual int OnInit (int argc, char* argv[]);
|
||||
/** \brief Destroys the system (must be called!) */
|
||||
virtual void OnDestroy ();
|
||||
|
||||
private:
|
||||
LogLevel mPrintLevel;
|
||||
/** \brief Stores all log messages that were sent to the Logging module
|
||||
* \todo Restrict the number of entries to be stored!
|
||||
*/
|
||||
std::vector<LogEntry> mLogEntries;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // _LOGGING_H
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef _LOGGINGLOBAL_H
|
||||
#define _LOGGINGLOBAL_H
|
||||
|
||||
namespace Engine {
|
||||
|
||||
enum LogLevel {
|
||||
LogLevelDebug = 0,
|
||||
LogLevelWarning,
|
||||
LogLevelMessage,
|
||||
LogLevelError
|
||||
};
|
||||
|
||||
/** \brief Represents a log message along with its level
|
||||
*/
|
||||
struct LogEntry {
|
||||
LogEntry (LogLevel level, const char* message) {
|
||||
mLevel = level;
|
||||
mMessage = message;
|
||||
}
|
||||
|
||||
/** \brief the level of the message */
|
||||
LogLevel mLevel;
|
||||
/** \brief the message itself */
|
||||
const char *mMessage;
|
||||
};
|
||||
|
||||
/* Global visible functions */
|
||||
|
||||
/** \brief Sets the level for which messages should be printed out */
|
||||
void SetLogPrintLevel (LogLevel print_level);
|
||||
|
||||
/** \brief Sends the Message to the Logging system */
|
||||
void LogError (const char* str, ...);
|
||||
/** \brief Sends the Message to the Logging system */
|
||||
void LogWarning (const char* str, ...);
|
||||
/** \brief Sends the Message to the Logging system */
|
||||
void LogMessage (const char* str, ...);
|
||||
/** \brief Sends the Message to the Logging system */
|
||||
void LogDebug (const char* str, ...);
|
||||
/** \brief Returns the last LogEntry sent to the Logging system */
|
||||
const LogEntry &GetLastLogEntry ();
|
||||
|
||||
}
|
||||
|
||||
#endif // _LOGGINGLOBAL_H
|
||||
@@ -0,0 +1,295 @@
|
||||
#include "ModelBase.h"
|
||||
|
||||
#include "PhysicsBase.h"
|
||||
#include "EntityBase.h"
|
||||
#include "EntityFactoryBase.h"
|
||||
|
||||
#include <coll2d.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
static ModelBase* ModelInstance = NULL;
|
||||
|
||||
/*
|
||||
* Inherited Module functions
|
||||
*/
|
||||
int ModelBase::OnInit (int argc, char* argv[]) {
|
||||
LogDebug ("Model Init");
|
||||
|
||||
ModelInstance = this;
|
||||
mKilledEntities.clear ();
|
||||
mEntityIdCounter = 0;
|
||||
mDeltaSec = 0.;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ModelBase::OnDestroy () {
|
||||
LogDebug ("Model Destroy");
|
||||
|
||||
std::map<unsigned int, EntityBase*>::iterator iter = mEntities.begin ();
|
||||
std::map<unsigned int, EntityBase*>::iterator next = iter;
|
||||
|
||||
// Since DestroyEntity () also erases the entry in mEntities iter gets
|
||||
// invalid. Therefore we have to store the iterator that follows iter
|
||||
while (iter != mEntities.end ()) {
|
||||
next = iter;
|
||||
next ++;
|
||||
DestroyEntity (iter->first);
|
||||
iter = next;
|
||||
}
|
||||
|
||||
ModelInstance = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Model specific functions
|
||||
*/
|
||||
void ModelBase::Process () {
|
||||
// Process the controllers and state of all entities
|
||||
std::map<unsigned int, EntityBase*>::iterator entity_iter = mEntities.begin();
|
||||
do {
|
||||
if (entity_iter->second == NULL) {
|
||||
LogError ("Entity with id %d does not exist!", entity_iter->first);
|
||||
assert (0);
|
||||
}
|
||||
entity_iter->second->Update(mDeltaSec);
|
||||
entity_iter++;
|
||||
} while (entity_iter != mEntities.end());
|
||||
|
||||
// simulate the world
|
||||
mPhysics->Simulate (mDeltaSec, this);
|
||||
|
||||
// remove killed entities
|
||||
unsigned int i;
|
||||
for (i = 0; i < mKilledEntities.size(); i++)
|
||||
UnregisterEntity (mKilledEntities[i]);
|
||||
|
||||
mKilledEntities.clear();
|
||||
}
|
||||
|
||||
EntityBase* ModelBase::CreateEntity (int type) {
|
||||
// Create a new entity id
|
||||
unsigned int entity_id = CreateEntityId();
|
||||
|
||||
// Call the event
|
||||
OnCreateEntity (type, entity_id);
|
||||
|
||||
// Create the entity
|
||||
EntityBase* result = mEntityFactory->CreateEntity (type);
|
||||
result->SetId (entity_id);
|
||||
|
||||
// And register it
|
||||
RegisterEntity (result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ModelBase::RegisterEntity (EntityBase* entity) {
|
||||
unsigned int id = entity->mId;
|
||||
LogDebug ("Registering Entity with id '%d'", id);
|
||||
|
||||
if (mEntities.find(id) != mEntities.end ()) {
|
||||
LogError ("Replacing Entity with id '%d'", id);
|
||||
assert (0);
|
||||
}
|
||||
|
||||
if (entity->mPhysicState)
|
||||
mPhysics->RegisterEntity (entity->mPhysicState);
|
||||
|
||||
mEntities[id] = entity;
|
||||
}
|
||||
|
||||
void ModelBase::KillEntity (const unsigned int id) {
|
||||
std::map<unsigned int, EntityBase*>::iterator iter = mEntities.find (id);
|
||||
|
||||
if (iter == mEntities.end ()) {
|
||||
LogError ("Could not kill Entity with id '%d': Entity not found!", id);
|
||||
assert (0);
|
||||
return;
|
||||
} else {
|
||||
EntityBase *entity = iter->second;
|
||||
|
||||
// call the event handler
|
||||
OnKillEntity (entity);
|
||||
|
||||
if (entity->mPhysicState) {
|
||||
entity->mPhysicState->mAlive = false;
|
||||
}
|
||||
|
||||
mKilledEntities.push_back (iter->first);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelBase::UnregisterEntity (const unsigned int id) {
|
||||
std::map<unsigned int, EntityBase*>::iterator iter = mEntities.find (id);
|
||||
|
||||
if (iter == mEntities.end ()) {
|
||||
LogError ("Could not unregister Entity with id '%d': Entity not found!", id);
|
||||
assert (0);
|
||||
return;
|
||||
} else {
|
||||
EntityBase *entity = iter->second;
|
||||
if (entity->mPhysicState) {
|
||||
mPhysics->UnregisterEntity (id);
|
||||
entity->mPhysicState = NULL;
|
||||
}
|
||||
|
||||
delete entity;
|
||||
|
||||
mEntities.erase (iter);
|
||||
}
|
||||
}
|
||||
|
||||
EntityBase* ModelBase::GetEntity (const unsigned int id) {
|
||||
std::map<unsigned int, EntityBase*>::iterator iter = mEntities.find (id);
|
||||
|
||||
if (iter != mEntities.end ()) {
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int ModelBase::CreateEntityId () {
|
||||
return ++mEntityIdCounter;
|
||||
}
|
||||
|
||||
void ModelBase::ClearEntities () {
|
||||
LogDebug ("Clearing all %d entities.", mEntities.size());
|
||||
|
||||
std::map<unsigned int, EntityBase*>::iterator iter = mEntities.begin ();
|
||||
std::map<unsigned int, EntityBase*>::iterator next = iter;
|
||||
|
||||
// Since DestroyEntity () also erases the entry in mEntities iter gets
|
||||
// invalid. Therefore we have to store the iterator that follows iter
|
||||
while (iter != mEntities.end ()) {
|
||||
next = iter;
|
||||
next ++;
|
||||
DestroyEntity (iter->first);
|
||||
iter = next;
|
||||
}
|
||||
|
||||
mEntityIdCounter = 0;
|
||||
}
|
||||
|
||||
unsigned int ModelBase::GetPlayerEntityId () {
|
||||
return mPlayerEntityId;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param collision_time The time when the collision occured relative to the start of the simulation frame
|
||||
*/
|
||||
void ModelBase::SendEntityCollisionEvent (const unsigned int reference_entity_id,
|
||||
const unsigned int incidence_entity_id, float collision_time, vector3d normal) {
|
||||
// Check whether we report the same contact over and over
|
||||
static unsigned int last_reference_entity_id = 0;
|
||||
static unsigned int last_incidence_entity_id = 0;
|
||||
static float last_collision_time = -1.;
|
||||
|
||||
if (!reference_entity_id || !incidence_entity_id)
|
||||
return;
|
||||
|
||||
if (last_reference_entity_id != 0) {
|
||||
if (last_reference_entity_id == reference_entity_id
|
||||
&& last_incidence_entity_id == incidence_entity_id
|
||||
&& last_collision_time == collision_time) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// update the last_* entries
|
||||
last_reference_entity_id = reference_entity_id;
|
||||
last_incidence_entity_id = incidence_entity_id;
|
||||
last_collision_time = collision_time;
|
||||
|
||||
// now we need to get the Entities and check whether we should
|
||||
// call EntityBase::CollisionEvent()
|
||||
EntityBase* reference_entity = GetEntity (reference_entity_id);
|
||||
EntityBase* incidence_entity = GetEntity (incidence_entity_id);
|
||||
|
||||
LogDebug ("Received collision type ref = %d type inc = %d",
|
||||
reference_entity->mType,
|
||||
incidence_entity->mType);
|
||||
|
||||
// If the incidence entity accepted the collision we can return, otherwise
|
||||
// we perform the symmetric collision event.
|
||||
if (incidence_entity->CollisionEvent (reference_entity))
|
||||
return;
|
||||
|
||||
reference_entity->CollisionEvent (incidence_entity);
|
||||
}
|
||||
|
||||
/*
|
||||
* Global functions
|
||||
*/
|
||||
unsigned int GetPlayerEntityId () {
|
||||
if (!ModelInstance) {
|
||||
LogError ("Couldn't create Entity: Model not initialized!");
|
||||
assert (0);
|
||||
}
|
||||
|
||||
return ModelInstance->GetPlayerEntityId ();
|
||||
}
|
||||
|
||||
float GetFrameDuration () {
|
||||
if (!ModelInstance) {
|
||||
LogError ("Couldn't create Entity: Model not initialized!");
|
||||
assert (0);
|
||||
}
|
||||
|
||||
return ModelInstance->GetFrameDuration ();
|
||||
}
|
||||
|
||||
EntityBase * CreateEntity (int type) {
|
||||
if (!ModelInstance) {
|
||||
LogError ("Couldn't create Entity: Model not initialized!");
|
||||
assert (0);
|
||||
}
|
||||
|
||||
EntityBase *result = ModelInstance->CreateEntity (type);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void DestroyEntity (unsigned int id) {
|
||||
if (!ModelInstance) {
|
||||
LogError ("Couldn't destroy Entity: Model not initialized!");
|
||||
assert (0);
|
||||
}
|
||||
|
||||
ModelInstance->UnregisterEntity (id);
|
||||
}
|
||||
|
||||
void KillEntity (unsigned int id) {
|
||||
if (!ModelInstance) {
|
||||
LogError ("Couldn't kill Entity: Model not initialized!");
|
||||
assert (0);
|
||||
}
|
||||
|
||||
ModelInstance->KillEntity (id);
|
||||
}
|
||||
|
||||
EntityBase * GetEntity (unsigned int id) {
|
||||
if (!ModelInstance) {
|
||||
LogError ("Couldn't execute GetEntity(): Model not initialized!");
|
||||
assert (0);
|
||||
}
|
||||
|
||||
return ModelInstance->GetEntity (id);
|
||||
}
|
||||
|
||||
EntityPhysicState * GetEntityPhysicState (unsigned int id) {
|
||||
EntityBase *entity = GetEntity (id);
|
||||
|
||||
if (entity)
|
||||
return entity->mPhysicState;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
#ifndef _MODELBASE_H
|
||||
#define _MODELBASE_H
|
||||
|
||||
#include "Engine.h"
|
||||
#include "EntityBase.h"
|
||||
|
||||
namespace Engine {
|
||||
|
||||
class Module;
|
||||
class PhysicsBase;
|
||||
class Events;
|
||||
class EntityFactoryBase;
|
||||
|
||||
struct EntityBase;
|
||||
|
||||
/** \brief Represents the current state of the Engine
|
||||
*
|
||||
* Represents the State of the Engine and is unaware of anything except itself.
|
||||
* It manages all Entities, Physics, etc.
|
||||
*
|
||||
* It has the following subsystems:
|
||||
* - Events
|
||||
* - Physics
|
||||
* - Variables
|
||||
*
|
||||
* \note
|
||||
* To create an Entity one must call Engine::CreateEntity() which will
|
||||
* allocate the Entity and performs all the required registrations by calling
|
||||
* Model::RegisterEntity().
|
||||
*/
|
||||
class ModelBase : public Module {
|
||||
public:
|
||||
/** Performs simulation, gamelogic, etc */
|
||||
virtual void Process ();
|
||||
/** Updates the timer */
|
||||
void UpdateTimer () {
|
||||
static float last_frame = 0;
|
||||
float current_frame = static_cast<float> (SDL_GetTicks ()) * 1.0e-3;
|
||||
mDeltaSec = current_frame - last_frame;
|
||||
last_frame = current_frame;
|
||||
}
|
||||
float GetFrameDuration () {
|
||||
return mDeltaSec;
|
||||
}
|
||||
|
||||
/** Adds the given Entity to the Model */
|
||||
void RegisterEntity (EntityBase *entity);
|
||||
/** Removes the Entity with the given id */
|
||||
void UnregisterEntity (const unsigned int id);
|
||||
/** Marks an Engine::Entity as killed so that it gets removed after the
|
||||
* simulation */
|
||||
void KillEntity (const unsigned int id);
|
||||
|
||||
/** Creates an Entity of the given type
|
||||
*
|
||||
* This calls the CreateEntity() function on the Model::mEntityFactory to
|
||||
* create the proper Entity and registers it to the required submodules
|
||||
* (so far only Model::mPhysics).
|
||||
*/
|
||||
EntityBase* CreateEntity (int type);
|
||||
/** Returns the Entity with the given id */
|
||||
EntityBase* GetEntity (const unsigned int id);
|
||||
/** Returns a unused id for an Entity */
|
||||
unsigned int CreateEntityId ();
|
||||
/** Removes all Entities */
|
||||
void ClearEntities ();
|
||||
|
||||
/** Returns the id of the entity the player is currently controlling */
|
||||
unsigned int GetPlayerEntityId ();
|
||||
|
||||
/** Notifies the gamelogic of a collision event */
|
||||
void SendEntityCollisionEvent (const unsigned int reference_entity_id,
|
||||
const unsigned int incidence_entity_id, float collision_time, vector3d normal);
|
||||
|
||||
protected:
|
||||
/** \brief Initializes the system */
|
||||
virtual int OnInit (int argc, char* argv[]);
|
||||
/** \brief Destroys the system (must be called!) */
|
||||
virtual void OnDestroy ();
|
||||
|
||||
/** \brief Gets called when an entity of the given type is being created */
|
||||
virtual void OnCreateEntity (const int type, const unsigned int id) {};
|
||||
/** \brief Gets called when an entity is marked to be killed */
|
||||
virtual void OnKillEntity (const EntityBase *entity) {};
|
||||
|
||||
|
||||
PhysicsBase *mPhysics;
|
||||
Events *mEvents;
|
||||
|
||||
/** \brief Creates Entities */
|
||||
EntityFactoryBase *mEntityFactory;
|
||||
|
||||
/** \brief contains all Engine::Entities */
|
||||
std::map<unsigned int, EntityBase *> mEntities;
|
||||
/** \brief contains all Engine::Entities that ceased to exist */
|
||||
std::vector<unsigned int> mKilledEntities;
|
||||
|
||||
unsigned int mEntityIdCounter;
|
||||
unsigned int mPlayerEntityId;
|
||||
|
||||
float mDeltaSec;
|
||||
|
||||
friend class ViewBase;
|
||||
friend class Engine;
|
||||
friend class Controller;
|
||||
};
|
||||
|
||||
/** \brief Creates an Entity of the given type and registers at the required modules *
|
||||
*
|
||||
* It allocates the memory needed to represent that specific type of Entity.
|
||||
* At also performs the required registrations at the various Modules.
|
||||
*
|
||||
* All Entities that are created with this function get also destroyed in
|
||||
* Model::Destroy () by calling DestroyEntity () for this Entity.
|
||||
*
|
||||
* \note All Entities must be created with this function if you intend to keep
|
||||
* the different Modules in sync!
|
||||
*/
|
||||
EntityBase * CreateEntity (int type);
|
||||
|
||||
/** \brief Frees the Memory required by the Entity and unregisters it
|
||||
*
|
||||
* This function also frees the memory the Entity is using in its
|
||||
* different representitions such as EntityVisualState and EntityPhysicState.
|
||||
*
|
||||
* It also unregisters the Entity from the different Modules where it was
|
||||
* registered by CreateEntity.
|
||||
*/
|
||||
void DestroyEntity (unsigned int id);
|
||||
/** \brief Tells the model that the entity is no more existant in the game
|
||||
* world */
|
||||
void KillEntity (unsigned int id);
|
||||
/** \brief Returns the Entity with the given id, NULL otherwise */
|
||||
EntityBase * GetEntity (unsigned int id);
|
||||
/** \brief Returns the physical state of the Entity with the given id, NULL otherwise */
|
||||
EntityPhysicState * GetEntityPhysicState (unsigned int id);
|
||||
|
||||
}
|
||||
|
||||
#endif // _MODEL_H
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef _MODELGLOBAL_H
|
||||
#define _MODELGLOBAL_H
|
||||
|
||||
namespace Engine {
|
||||
|
||||
/** \brief Adds the function callback as command for the given name*/
|
||||
unsigned int GetPlayerEntityId ();
|
||||
|
||||
/** \brief Returns the duration of the frame in seconds */
|
||||
float GetFrameDuration ();
|
||||
|
||||
}
|
||||
|
||||
#endif /* _MODELGLOBAL_H */
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#ifndef MODULE_H
|
||||
#define MODULE_H
|
||||
|
||||
namespace Engine {
|
||||
|
||||
/** \brief Base class for the separate modules
|
||||
*
|
||||
* All Modules that are managed by the Engine::Engine base Module. Everything
|
||||
* else is a Submodule of that or a Submodule of a Submodule.
|
||||
*/
|
||||
class Module {
|
||||
public:
|
||||
/** \brief Initializes the Module
|
||||
*
|
||||
* \note This function must only return if it was able to initialize
|
||||
* successfully, otherwise it should log an error with LogError and exit
|
||||
* the program itself!
|
||||
*
|
||||
* In general at first the Submodules get initialized and then the Module
|
||||
* that has pointers to the Submodules. Exception: The main Module
|
||||
* Engine::Engine.
|
||||
*
|
||||
* \note
|
||||
* The function Engine::OnInit () performs the allocation
|
||||
* and Initialization of all its Submodules.
|
||||
*/
|
||||
virtual int Init (int argc, char* argv[]) { return OnInit (argc, argv); }
|
||||
/** \brief Frees the used memory of the Module
|
||||
*
|
||||
* The Destroy function is always called at first for the Module itself
|
||||
* and then for its submodules so that a Module is still completely
|
||||
* working. Again for the main Module Engine::Engine the reverse is the
|
||||
* case (such as in Module::Init).
|
||||
*/
|
||||
virtual void Destroy () { OnDestroy (); }
|
||||
/** \brief Calls the function that registers its commands to the
|
||||
* Commandsystem */
|
||||
virtual void RegisterCommands () { OnRegisterCommands (); }
|
||||
|
||||
protected:
|
||||
/** \brief The actual function being called when Init () is called */
|
||||
virtual int OnInit (int argc, char* argv[]) = 0;
|
||||
/** \brief Frees the memory */
|
||||
virtual void OnDestroy () { };
|
||||
/** \brief Registers the commands of the Module */
|
||||
virtual void OnRegisterCommands () { };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* MODULE_H */
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef OVERLAY
|
||||
#define OVERLAY
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
class OverlayBase {
|
||||
public:
|
||||
OverlayBase () {};
|
||||
virtual ~OverlayBase() {};
|
||||
|
||||
virtual bool OnKeyDown (const SDL_keysym &keysym) { return false; };
|
||||
virtual bool OnKeyUp (const SDL_keysym &keysym) { return false; };
|
||||
virtual bool OnMouseButtonUp (Uint8 button, Uint16 xpos, Uint16 ypos) { return false; };
|
||||
virtual bool OnMouseButtonDown (Uint8 button, Uint16 xpos, Uint16 ypos) { return false; };
|
||||
|
||||
virtual void Draw () = 0;
|
||||
|
||||
void _strange_function_for_vtable () {};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* OVERLAY */
|
||||
@@ -0,0 +1,604 @@
|
||||
#include "PhysicsBase.h"
|
||||
#include "EntityBase.h"
|
||||
|
||||
// needed for GetEntityGameState() in ProcessCollisionEvent()
|
||||
#include "ModelBase.h"
|
||||
|
||||
#include "coll2d.h"
|
||||
|
||||
#define EPSILON 1.0e-4
|
||||
|
||||
namespace Engine {
|
||||
|
||||
/*
|
||||
* Inherited Module functions
|
||||
*/
|
||||
int PhysicsBase::OnInit (int argc, char* argv[]) {
|
||||
LogDebug ("Physics Init");
|
||||
mEntities.clear ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PhysicsBase::OnDestroy () {
|
||||
LogDebug ("Physics Destroy");
|
||||
}
|
||||
|
||||
/*
|
||||
* Module specific functions
|
||||
*/
|
||||
|
||||
void PhysicsBase::Move (float delta_msec) {
|
||||
EntityPhysicState* entity = NULL;
|
||||
std::map<unsigned int, EntityPhysicState*>::iterator entity_iter;
|
||||
std::map<unsigned int, EntityPhysicState*>::iterator collision_iter;
|
||||
vector3d velocity, orientation;
|
||||
|
||||
for (entity_iter = mEntities.begin (); entity_iter != mEntities.end(); entity_iter++){
|
||||
entity = entity_iter->second;
|
||||
velocity = entity->GetVelocity ();
|
||||
|
||||
if (velocity.length2() == 0.)
|
||||
continue;
|
||||
|
||||
CheckContactCache (entity);
|
||||
|
||||
entity->SetPosition (entity->GetPosition () + velocity * delta_msec);
|
||||
entity->SetOrientation (vector3d(0., entity->GetOrientation()[1] + entity->GetAngleVelocity() * delta_msec, 0.));
|
||||
}
|
||||
}
|
||||
|
||||
int PhysicsBase::Simulate (float msec, ModelBase* model) {
|
||||
vector3d velocity, orientation;
|
||||
|
||||
unsigned int entity_a_id, entity_b_id;
|
||||
int resolve_steps = 0;;
|
||||
float current_time = 0, stepsize = msec / (float) 10;
|
||||
|
||||
while (current_time < msec) {
|
||||
if (msec - current_time < stepsize)
|
||||
stepsize = msec - current_time;
|
||||
|
||||
coll2d::CollisionInfo info;
|
||||
bool collision_result = false;
|
||||
|
||||
collision_result = CalcNextCollision (stepsize, entity_a_id, entity_b_id, info);
|
||||
|
||||
if (collision_result == 0) {
|
||||
// there is no collision, so we integrate to the end of
|
||||
// the timestep
|
||||
current_time += stepsize;
|
||||
Move (stepsize);
|
||||
} else {
|
||||
LogDebug ("Collision between %u and %u", entity_a_id, entity_b_id);
|
||||
float collision_remaining_step = stepsize;
|
||||
resolve_steps = 0;
|
||||
|
||||
// This is the collision loop. It loops until there is no collision any
|
||||
// more within the stepsize.
|
||||
while (collision_remaining_step > 0.) {
|
||||
// with this we count how often we iterate through and can
|
||||
// detect certain false behaviour
|
||||
resolve_steps ++;
|
||||
|
||||
// info.time tells us in what time the contact will happen and
|
||||
// theoretically we can move to that point, however due to round-off
|
||||
// errors we might end up in a situation where the Entities overlap
|
||||
// which we must prevent to keep the collision detection working.
|
||||
//
|
||||
// Therefore we only move to a portion of the time and resolve the
|
||||
// collision then. This alpha variable controls how much of the time
|
||||
// we skip.
|
||||
float alpha = 0.001;
|
||||
|
||||
// If the timestep is already very small, we try to resolve it
|
||||
// immediately.
|
||||
if (info.time < EPSILON ) {
|
||||
// if the timestep is too small we simply resolve the collision and
|
||||
// do not move beforehang
|
||||
LogDebug ("Time step too small ==> Resolving Step immediately");
|
||||
ResolveCollision (0., entity_a_id, entity_b_id, info);
|
||||
// Send the collision event to the Model (if we have one)
|
||||
if (model) {
|
||||
model->SendEntityCollisionEvent (entity_a_id, entity_b_id, info.time, info.normal);
|
||||
}
|
||||
// collision_remaining_step -= 1.0e-4;
|
||||
} else {
|
||||
Move (info.time * (1 - alpha));
|
||||
LogDebug ("Resolving Step between %u and %u t = %f alpha = %f", entity_a_id, entity_b_id, info.time, alpha);
|
||||
ResolveCollision (info.time * (1 - alpha), entity_a_id, entity_b_id, info);
|
||||
// Send the collision event to the Model (if we have one)
|
||||
if (model) {
|
||||
model->SendEntityCollisionEvent (entity_a_id, entity_b_id, info.time, info.normal);
|
||||
}
|
||||
collision_remaining_step -= info.time * (1 - alpha);
|
||||
}
|
||||
|
||||
// At this point we resolved the collision we had found. Now we need
|
||||
// to check whether there is a new one
|
||||
collision_result = CalcNextCollision (collision_remaining_step, entity_a_id, entity_b_id, info);
|
||||
|
||||
// If there was none, we happily move on to the end of the frame and
|
||||
// set collision_remaining_step to 0 so that we jump out of the
|
||||
// collision loop.
|
||||
if (!collision_result) {
|
||||
Move (collision_remaining_step);
|
||||
collision_remaining_step = 0.;
|
||||
break;
|
||||
}
|
||||
|
||||
assert (resolve_steps <= 50);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Postcondition: we simulated exactly msec milliseconds, no less, no more! */
|
||||
assert (current_time == msec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PhysicsBase::RegisterEntity (EntityPhysicState* entity) {
|
||||
unsigned int id = entity->mId;
|
||||
LogDebug ("Registering EntityPhysicState with id '%d'", id);
|
||||
if (mEntities.find (id) == mEntities.end ())
|
||||
mEntities[id] = entity;
|
||||
else {
|
||||
LogError ("Physics already has registered an Entity with id '%d'", id);
|
||||
assert (0);
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsBase::UnregisterEntity (const unsigned int id) {
|
||||
std::map<unsigned int, EntityPhysicState*>::iterator iter = mEntities.find(id);
|
||||
LogDebug ("Unegistering EntityPhysicState with id '%d'", id);
|
||||
|
||||
if (iter != mEntities.end ()) {
|
||||
// Remove all the references of existing contacts to the Entity that is
|
||||
// going to be deleted.
|
||||
std::map<unsigned int, vector3d>::iterator temp_iter, contact_iter = iter->second->mContactNormals.begin();
|
||||
|
||||
while (contact_iter != iter->second->mContactNormals.end()) {
|
||||
temp_iter = contact_iter;
|
||||
contact_iter ++;
|
||||
|
||||
ContactCacheRemove (id, temp_iter->first);
|
||||
}
|
||||
|
||||
// Remove the Entity from mEntities and erase the Entity
|
||||
EntityPhysicState* entity_physic_state = iter->second;
|
||||
mEntities.erase (iter);
|
||||
|
||||
// We also have to delete the state!
|
||||
if (entity_physic_state->mShape)
|
||||
delete entity_physic_state->mShape;
|
||||
|
||||
delete entity_physic_state;
|
||||
} else {
|
||||
LogError ("Could not unegister EntityPhysicState with id '%d': Entity not found!", id);
|
||||
assert (0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function also sorts out collisions that might be invalid such as
|
||||
* Particle-Particle collision and the like.
|
||||
*/
|
||||
inline bool PhysicsBase::CheckPossibleCollisionPair (EntityPhysicState* entity_a, EntityPhysicState* entity_b) {
|
||||
// no collision checks against itself
|
||||
if (entity_a == entity_b)
|
||||
return false;
|
||||
|
||||
// no checks if both are static
|
||||
if (entity_a->mStatic && entity_a->mStatic)
|
||||
return false;
|
||||
|
||||
// no checks if both are particles
|
||||
if (entity_a->mBaseType == EntityBaseTypeParticle
|
||||
&& entity_b->mBaseType == EntityBaseTypeParticle)
|
||||
return false;
|
||||
|
||||
// no checks if both are particles
|
||||
if (entity_a->mBaseType == EntityBaseTypeBlock
|
||||
&& entity_b->mBaseType == EntityBaseTypeBlock)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param stepsize The timestep for which we want to check whether a
|
||||
* collision occurs.
|
||||
* \param reference_entity_id If a collision occurs the Id of the entity that
|
||||
* is the reference entity is stored in this variable.
|
||||
* \param incidence_entity_id If a collision occurs the Id of the entity that
|
||||
* crashes into the reference entity is stored in this variable.
|
||||
* \param info Contains information about the collision (normal, time, point)
|
||||
*
|
||||
* This function calls PhysicsBase::CheckPossibleCollisionPair() to sort out
|
||||
* invalid collision pairs.
|
||||
*/
|
||||
bool PhysicsBase::CalcNextCollision (
|
||||
float stepsize,
|
||||
unsigned int &reference_entity_id,
|
||||
unsigned int &incidence_entity_id,
|
||||
coll2d::CollisionInfo &info) {
|
||||
std::map<unsigned int, EntityPhysicState*>::iterator collision_iter;
|
||||
std::map<unsigned int, EntityPhysicState*>::iterator collision_ref;
|
||||
|
||||
// We have to find the next collision, so we check everything and
|
||||
// take the first one that will happen.
|
||||
coll2d::CollisionInfo temp_info;
|
||||
info.time = 2.;
|
||||
|
||||
for (collision_ref = mEntities.begin (); collision_ref != mEntities.end (); collision_ref ++) {
|
||||
if (collision_ref->second->mId != 0) {
|
||||
collision_ref->second->UpdateShape();
|
||||
}
|
||||
}
|
||||
|
||||
for (collision_ref = mEntities.begin (); collision_ref != mEntities.end (); collision_ref ++) {
|
||||
if (collision_ref->second->mAlive == false)
|
||||
continue;
|
||||
for (collision_iter = collision_ref; collision_iter != mEntities.end (); collision_iter ++) {
|
||||
if (collision_iter->second->mAlive == false)
|
||||
continue;
|
||||
|
||||
if (!CheckPossibleCollisionPair(collision_ref->second, collision_iter->second))
|
||||
continue;
|
||||
|
||||
EntityPhysicState *entity_a, *entity_b;
|
||||
entity_a = collision_ref->second;
|
||||
entity_b = collision_iter->second;
|
||||
|
||||
int coll2d_result = coll2d::check_collision (stepsize, entity_a->mShape, entity_b->mShape, &temp_info);
|
||||
|
||||
if (!HandleColl2dError (coll2d_result, stepsize, entity_a, entity_b, temp_info)) {
|
||||
LogError ("Could not handle coll2d error: %d\n", coll2d_result);
|
||||
assert (0);
|
||||
}
|
||||
|
||||
if (coll2d_result > 0 && temp_info.time < info.time ) {
|
||||
info = temp_info;
|
||||
|
||||
assert (info.reference_shape >= 0);
|
||||
if (info.reference_shape == 0) {
|
||||
reference_entity_id = collision_ref->first;
|
||||
incidence_entity_id = collision_iter->first;
|
||||
} else {
|
||||
reference_entity_id = collision_iter->first;
|
||||
incidence_entity_id = collision_ref->first;
|
||||
//assert (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (info.time != 2.)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function updates the velocity of the Entity with id of
|
||||
* incidence_entity_id so that it no more is in collision with with Entity
|
||||
* with id reference_entity_id. Additionally to that we also cache the
|
||||
* contact normals and check against them so that the new velocity does not
|
||||
* violate previous contacts.
|
||||
*
|
||||
* We store the cached contact normals both in the incidence and the reference
|
||||
* entity and we have to make sure that these references get cleared once one
|
||||
* of the two get deleted! This is done in PhysicsBase::UnregisterEntity().
|
||||
*/
|
||||
void PhysicsBase::ResolveCollision (float stepsize, unsigned int reference_entity_id, unsigned int incidence_entity_id, coll2d::CollisionInfo &info) {
|
||||
EntityPhysicState* reference_entity = mEntities[reference_entity_id];
|
||||
EntityPhysicState* incidence_entity = mEntities[incidence_entity_id];
|
||||
|
||||
if (!reference_entity || !incidence_entity) {
|
||||
LogError ("Invalid entity IDs passed to %s: %u and %u", __FUNCTION__, reference_entity_id, incidence_entity_id);
|
||||
}
|
||||
assert (reference_entity && incidence_entity);
|
||||
|
||||
// So far only resolving of collision of sphere collisions is
|
||||
// allowed
|
||||
assert (dynamic_cast<coll2d::Sphere*> (incidence_entity->mShape));
|
||||
|
||||
// First we calculate the velocity along the normal and then we calculate
|
||||
// the velocity that is tangential to the plane and set the new velocity to
|
||||
// it.
|
||||
vector3d new_velocity = incidence_entity->mVelocity;
|
||||
new_velocity -= reference_entity->mVelocity;
|
||||
|
||||
// It should be greater zero otherwise there was an error in the collision
|
||||
// detection.
|
||||
assert (new_velocity.length2 ());
|
||||
|
||||
// The scalar proj tells us how far we went along the normal
|
||||
float proj = new_velocity * info.normal;
|
||||
// As there is a collision, and the incidence_entity is moving towards the
|
||||
// plane, this value must be strictly smaller than zero, otherwise we would
|
||||
// not penetrate the plane.
|
||||
if (proj > 0.) {
|
||||
LogError ("Projection invalid: %e", proj);
|
||||
info.doPrint ("Collision Info:\n");
|
||||
}
|
||||
assert (proj < 0.);
|
||||
|
||||
// Collision handling start:
|
||||
// This is the code that tells us how we deal with collisions and how to
|
||||
// prevent them. To get real dynamics one has to adjust this section:
|
||||
vector3d old_velocity = incidence_entity->mVelocity;
|
||||
new_velocity = old_velocity + info.normal * proj * (-1.0);
|
||||
incidence_entity->SetVelocity (new_velocity);
|
||||
// Collision handling end
|
||||
|
||||
// And we also add the normal to the cached contacts for both incidence
|
||||
// and reference entity
|
||||
ContactCacheAdd (incidence_entity, reference_entity, info.normal);
|
||||
|
||||
// Now we check whether we are violating any of the cached contacts. For
|
||||
// this we loop through all contacts and try to adjust the velocity of
|
||||
// incidence_entity until we no more violate the cached contacts.
|
||||
std::map<unsigned int, vector3d>::iterator iter = incidence_entity->mContactNormals.begin();
|
||||
int readjust = 0;
|
||||
while (iter != incidence_entity->mContactNormals.end()) {
|
||||
vector3d contact_normal = iter->second;
|
||||
float contact_velocity = new_velocity * contact_normal;
|
||||
|
||||
if (contact_velocity < 0.) {
|
||||
if (reference_entity_id == iter->first) {
|
||||
// In this case, the projection was not good enough. We simultaneously
|
||||
// damp the velocity and push a little harder. If it was damped too
|
||||
// much or we had to readjust too often, we set the velocity to zero.
|
||||
LogDebug ("Resolved collision needs to be readjusted");
|
||||
new_velocity = incidence_entity->GetVelocity();
|
||||
new_velocity *= 0.5;
|
||||
if (new_velocity.length2() < EPSILON)
|
||||
new_velocity.setValues (0., 0., 0.);
|
||||
else
|
||||
new_velocity += info.normal * 0.001;
|
||||
incidence_entity->SetVelocity (new_velocity);
|
||||
readjust++;
|
||||
|
||||
// More than 10 readjusts? -> set velocity to zero
|
||||
if (readjust > 10)
|
||||
new_velocity.setValues (0., 0., 0.);
|
||||
|
||||
// and we redo all the checking:
|
||||
iter = incidence_entity->mContactNormals.begin();
|
||||
continue;
|
||||
}
|
||||
|
||||
// In this case the proposed velocity is violating another contact
|
||||
// and we set the velocity to zero.
|
||||
LogDebug ("Cached collision: %e -> resetting velocity", contact_velocity);
|
||||
// contact_normal.print ("contact normal: ");
|
||||
new_velocity.setValues (0., 0., 0.);
|
||||
incidence_entity->mVelocity = new_velocity;
|
||||
} else if (contact_velocity > 0.01) {
|
||||
// If we move sufficiently fast away from a contact we remove the
|
||||
// contact from the cache.
|
||||
|
||||
// * Attention! * As the function ContactCacheRemove() deletes an entry
|
||||
// of mContactNormals we have to increase the iterator *before* we
|
||||
// remove the cache. Otherwise the iterator might become invalid!
|
||||
unsigned int contact_id = iter->first;
|
||||
iter++;
|
||||
|
||||
ContactCacheRemove (contact_id, incidence_entity_id);
|
||||
|
||||
continue;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Contact Cache Functions
|
||||
*/
|
||||
void PhysicsBase::ContactCacheAdd (EntityPhysicState* incidence_entity, EntityPhysicState* reference_entity, vector3d normal) {
|
||||
incidence_entity->mContactNormals[reference_entity->mId] = normal;
|
||||
reference_entity->mContactNormals[incidence_entity->mId] = normal * -1.;
|
||||
|
||||
LogDebug ("Adding normal (%f,%f,%f) id=%d to entity %d",
|
||||
normal[0], normal[1], normal[2],
|
||||
reference_entity->mId, incidence_entity->mId);
|
||||
LogDebug ("Adding normal (%f,%f,%f) id=%d to entity %d",
|
||||
normal[0] * -1., normal[1] * -1., normal[2] * -1.,
|
||||
incidence_entity->mId, reference_entity->mId);
|
||||
}
|
||||
|
||||
void PhysicsBase::ContactCacheRemove (unsigned int entity_a_id, unsigned int entity_b_id) {
|
||||
assert (entity_a_id != entity_b_id);
|
||||
|
||||
// LogDebug ("Removing start %d and %d", entity_a_id, entity_b_id);
|
||||
|
||||
EntityPhysicState *entity_a, *entity_b;
|
||||
|
||||
#ifdef WIN32
|
||||
entity_a = mEntities[entity_a_id];
|
||||
entity_b = mEntities[entity_b_id];
|
||||
#else
|
||||
entity_a = mEntities.at(entity_a_id);
|
||||
entity_b = mEntities.at(entity_b_id);
|
||||
#endif
|
||||
|
||||
// Check the entries exist
|
||||
assert (entity_a->mContactNormals.find (entity_b_id) != entity_a->mContactNormals.end());
|
||||
assert (entity_b->mContactNormals.find (entity_a_id) != entity_b->mContactNormals.end());
|
||||
|
||||
#ifdef WIN32
|
||||
vector3d contact_normal = entity_a->mContactNormals[entity_b_id];
|
||||
#else
|
||||
vector3d contact_normal = entity_a->mContactNormals.at(entity_b_id);
|
||||
#endif
|
||||
|
||||
LogDebug ("Removing normal (%f,%f,%f) id=%d from entity %d",
|
||||
contact_normal[0], contact_normal[1], contact_normal[2],
|
||||
entity_a_id, entity_b_id);
|
||||
entity_a->mContactNormals.erase (entity_a->mContactNormals.find(entity_b_id));
|
||||
|
||||
#ifdef WIN32
|
||||
contact_normal = entity_b->mContactNormals[entity_a_id];
|
||||
#else
|
||||
contact_normal = entity_b->mContactNormals.at(entity_a_id);
|
||||
#endif
|
||||
|
||||
LogDebug ("Removing normal (%f,%f,%f) id=%d from entity %d",
|
||||
contact_normal[0], contact_normal[1], contact_normal[2],
|
||||
entity_b_id, entity_a_id);
|
||||
entity_b->mContactNormals.erase (entity_b->mContactNormals.find(entity_a_id));
|
||||
|
||||
// LogDebug ("Removing done!");
|
||||
}
|
||||
|
||||
/** \brief Checks whether we are still in contact with the entities stored in mContactNormals
|
||||
*
|
||||
* To check whether we still are in contact, we modify temporarily the
|
||||
* velocity of the given Entity that it moves towards the contact point (i.e.
|
||||
* we add the negative normal to the velocity) and re-check for a collision.
|
||||
* If the collision has a time value of 0.0 and the reported normal stays the
|
||||
* same, we know, that the two Entities are still in contact. If not, we lost
|
||||
* contact.
|
||||
*
|
||||
* We can skip the test, if the scalar product of the normal and velocity are
|
||||
* positive (in this case we move away from the plane)
|
||||
*/
|
||||
void PhysicsBase::CheckContactCache (EntityPhysicState* entity) {
|
||||
std::map<unsigned int, vector3d>::iterator contacts_iter, current_iter;
|
||||
|
||||
contacts_iter = entity->mContactNormals.begin();
|
||||
while (contacts_iter != entity->mContactNormals.end()) {
|
||||
// * Attention! *
|
||||
// current_iter can be used throughout this environment and contacts_iter
|
||||
// can already now be increased as it *must not* be used! This is due to
|
||||
// the nature of ContactCachRemove() which might make contacts_iter
|
||||
// invalid if we were using that.
|
||||
current_iter = contacts_iter;
|
||||
contacts_iter ++;
|
||||
|
||||
unsigned int contact_entity_id = contacts_iter->first;
|
||||
|
||||
#ifdef WIN32
|
||||
EntityPhysicState* contact_entity = mEntities[contact_entity_id];
|
||||
#else
|
||||
EntityPhysicState* contact_entity = mEntities.at (contact_entity_id);
|
||||
#endif
|
||||
|
||||
vector3d normal = contacts_iter->second;
|
||||
vector3d old_velocity = entity->GetVelocity();
|
||||
|
||||
// If we already move away from the normal, we delete the contact.
|
||||
if (normal * old_velocity > 0.01) {
|
||||
LogDebug ("Lost Contact with entity %d!", current_iter->first);
|
||||
ContactCacheRemove (entity->mId, current_iter->first);
|
||||
continue;
|
||||
} else {
|
||||
vector3d new_velocity (old_velocity);
|
||||
new_velocity -= normal;
|
||||
entity->SetVelocity (new_velocity);
|
||||
|
||||
entity->UpdateShape();
|
||||
contact_entity->UpdateShape();
|
||||
|
||||
coll2d::CollisionInfo info;
|
||||
int coll2d_result;
|
||||
|
||||
coll2d_result = coll2d::check_collision (1.0, entity->mShape, contact_entity->mShape, &info);
|
||||
|
||||
if (!HandleColl2dError (coll2d_result, 1.0, entity, contact_entity, info)) {
|
||||
// error
|
||||
LogError ("Error when performing collision check: %s\n", __FUNCTION__);
|
||||
assert (0);
|
||||
}
|
||||
|
||||
if (coll2d_result == 0) {
|
||||
// no contact, so delete it:
|
||||
LogDebug ("Lost Contact with entity %d!", current_iter->first);
|
||||
ContactCacheRemove (entity->mId, current_iter->first);
|
||||
|
||||
entity->SetVelocity (old_velocity);
|
||||
continue;
|
||||
} else if ( coll2d_result > 0){
|
||||
// contact
|
||||
if (info.time != 0. || normal != info.normal) {
|
||||
LogError ("Something strange happened when checking for contacts in %s\n", __FUNCTION__);
|
||||
assert (0);
|
||||
}
|
||||
}
|
||||
|
||||
entity->SetVelocity (old_velocity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* So far we ignore overlapping if one entity is an EntityBaseTypeActor and
|
||||
* the other a EntityBaseTypeParticle.
|
||||
*
|
||||
* If this function returns true everything is ok and we can safely continue
|
||||
* otherwise it is recommended to quit the application.
|
||||
*
|
||||
* \returns true if there was no error at all or we were able to deal with it
|
||||
*/
|
||||
bool PhysicsBase::HandleColl2dError (int coll2d_result, float stepsize,
|
||||
EntityPhysicState* entity_a, EntityPhysicState* entity_b, coll2d::CollisionInfo &info)
|
||||
{
|
||||
if (coll2d_result < 0) {
|
||||
if (coll2d_result == CHECK_ERROR_OVERLAP) {
|
||||
// this can happen if an Actor is faster than its thrown Particle,
|
||||
// we ignore this for now
|
||||
/// \todo Handle overlaps of Actors and Particles better or define clear guidelines. Note this also in Entity.h
|
||||
if ( (entity_a->mBaseType == EntityBaseTypeParticle && entity_b->mBaseType == EntityBaseTypeActor)
|
||||
|| (entity_b->mBaseType == EntityBaseTypeParticle && entity_a->mBaseType == EntityBaseTypeActor) )
|
||||
LogDebug ("Ignoring CHECK_ERROR_OVERLAP");
|
||||
return true;
|
||||
} else {
|
||||
LogError ("coll2d Error: %d (stepsize = %f, id_a = %d, id_b = %d)", coll2d_result, stepsize, entity_a->mId, entity_b->mId);
|
||||
entity_a->mShape->doPrint ("Debug: entity_a");
|
||||
entity_b->mShape->doPrint ("Debug: entity_b");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
EntityPhysicState* CreateEntityPhysicState (EntityBaseType type, unsigned int id) {
|
||||
EntityPhysicState* entity_physics = new EntityPhysicState ();
|
||||
if (!entity_physics) {
|
||||
LogError ("Could not allocate enough memory for EntityPhysicState of type '%d'", type);
|
||||
assert (0);
|
||||
}
|
||||
// default values for all Entities
|
||||
entity_physics->mId = id;
|
||||
entity_physics->mBaseType = type;
|
||||
|
||||
// specific values for each Entity type
|
||||
if (type == EntityBaseTypeNone) {
|
||||
entity_physics->mShape = new coll2d::Sphere (0.01);
|
||||
assert (entity_physics->mShape);
|
||||
} else if (type == EntityBaseTypeActor) {
|
||||
entity_physics->mShape = new coll2d::Sphere (0.4);
|
||||
assert (entity_physics->mShape);
|
||||
} else if (type == EntityBaseTypeBlock) {
|
||||
entity_physics->mShape = new coll2d::Polygon (4);
|
||||
assert (entity_physics->mShape);
|
||||
|
||||
static_cast<coll2d::Polygon*> (entity_physics->mShape)->setVertice (0, vector3d (-0.5, 0., 0.5));
|
||||
static_cast<coll2d::Polygon*> (entity_physics->mShape)->setVertice (1, vector3d (0.5, 0., 0.5));
|
||||
static_cast<coll2d::Polygon*> (entity_physics->mShape)->setVertice (2, vector3d (0.5, 0., -0.5));
|
||||
static_cast<coll2d::Polygon*> (entity_physics->mShape)->setVertice (3, vector3d (-0.5, 0., -0.5));
|
||||
} else if (type == EntityBaseTypeParticle) {
|
||||
entity_physics->mShape = new coll2d::Sphere (0.05);
|
||||
assert (entity_physics->mShape);
|
||||
} else {
|
||||
LogError ("No EntityPhysicState defined for Entity type '%d'", type);
|
||||
assert (0);
|
||||
}
|
||||
|
||||
return entity_physics;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
#ifndef _PHYSICSBASE_H
|
||||
#define _PHYSICSBASE_H
|
||||
|
||||
#include "Engine.h"
|
||||
#include "EntityBase.h"
|
||||
|
||||
namespace coll2d {
|
||||
struct CollisionInfo;
|
||||
}
|
||||
|
||||
/// \todo get rid of this forward declaration somehow
|
||||
struct vector3d;
|
||||
|
||||
namespace Engine {
|
||||
|
||||
class Module;
|
||||
class Events;
|
||||
|
||||
class EntityPhysicState;
|
||||
|
||||
/** \brief Performs the physical simulation of all Entities
|
||||
*
|
||||
* This class defines how the physical simulation is performed. Especially how
|
||||
* collisions are treated is defined in the function
|
||||
* Physics::ResolveCollision() . This function can be modified to simulate
|
||||
* dynamics effects such as friction, bouncing, stacking etc..
|
||||
*
|
||||
* \todo When running along multiple boxes that are perfectly aligned one hangs from time to time at the last box
|
||||
*/
|
||||
class PhysicsBase : public Module {
|
||||
public:
|
||||
/** \brief Performs the simulation for the next msec milliseconds
|
||||
* \param msec The amount of time that is to be simulated
|
||||
* \param model A pointer to the model that will be used to pass on collision events.*/
|
||||
virtual int Simulate (float msec, ModelBase* model = NULL);
|
||||
/** \brief Registers the physical state of an Entity */
|
||||
virtual void RegisterEntity (EntityPhysicState* entity);
|
||||
/** \brief Unregisters the physical state of an Entity */
|
||||
virtual void UnregisterEntity (const unsigned int id);
|
||||
|
||||
protected:
|
||||
/** \brief Initializes the system */
|
||||
virtual int OnInit (int argc, char* argv[]);
|
||||
/** \brief Destroys the system (must be called!) */
|
||||
virtual void OnDestroy ();
|
||||
|
||||
/** \brief Moves all Entities for delta_msec milliseconds (can be
|
||||
* negative!) */
|
||||
void Move (float delta_msec);
|
||||
|
||||
/** \brief Checks whether two given Entities can collide */
|
||||
bool CheckPossibleCollisionPair (EntityPhysicState* entity_a, EntityPhysicState* entity_b);
|
||||
/** \brief Calculates the next pair of Entities that will collide */
|
||||
bool CalcNextCollision (float stepsize,
|
||||
unsigned int &reference_entity_id,
|
||||
unsigned int &incidence_entity_id,
|
||||
coll2d::CollisionInfo &info);
|
||||
/** \brief Resolves the collision that CalcNextCollision has found
|
||||
* It resolves a found collision and prevents interpenetration of cached contacts.
|
||||
*/
|
||||
void ResolveCollision (float stepsize,
|
||||
unsigned int reference_entity_id,
|
||||
unsigned int incidence_entity_id,
|
||||
coll2d::CollisionInfo &info);
|
||||
|
||||
/** \brief Contains all Entities with a physical state */
|
||||
std::map<unsigned int, EntityPhysicState*> mEntities;
|
||||
|
||||
private:
|
||||
/** \brief Caches the contact information between two entities
|
||||
*/
|
||||
void ContactCacheAdd (EntityPhysicState* incidence_entity, EntityPhysicState* reference_entity, vector3d normal);
|
||||
/** \brief Removes the contact cache information of two entities in contact
|
||||
*/
|
||||
void ContactCacheRemove (unsigned int entity_a_id, unsigned int entity_b_id);
|
||||
/** \brief Checks whether the entries in the contact cache are still valid
|
||||
*/
|
||||
void CheckContactCache (EntityPhysicState* entity);
|
||||
|
||||
/** \brief Allows to ignore certain kinds of errors reported by coll2d
|
||||
*/
|
||||
bool HandleColl2dError (int coll2d_result, float stepsize,
|
||||
EntityPhysicState* entity_a, EntityPhysicState* entity_b, coll2d::CollisionInfo &info);
|
||||
};
|
||||
|
||||
/** \brief Creates an EntityPhysicState with all the required information */
|
||||
EntityPhysicState* CreateEntityPhysicState (EntityBaseType type, unsigned int id);
|
||||
|
||||
}
|
||||
|
||||
#endif // _PHYSICSBASE_H
|
||||
@@ -0,0 +1,149 @@
|
||||
#include "EntityBase.h"
|
||||
|
||||
#include "coll2d.h"
|
||||
|
||||
namespace Engine {
|
||||
|
||||
/** \brief Copy constructor */
|
||||
inline EntityPhysicState::EntityPhysicState (const EntityPhysicState& state):
|
||||
mId (state.mId),
|
||||
mBaseType (state.mBaseType),
|
||||
mPosition (state.mPosition),
|
||||
mOrientation (state.mOrientation),
|
||||
mVelocity (state.mVelocity),
|
||||
mAngleVelocity (state.mAngleVelocity),
|
||||
mStatic (state.mStatic),
|
||||
mAlive (state.mAlive),
|
||||
mContactNormals(state.mContactNormals)
|
||||
{
|
||||
mShape = state.mShape->getCopy();
|
||||
};
|
||||
|
||||
/** \brief Assignment operator */
|
||||
inline EntityPhysicState& EntityPhysicState::operator= (const EntityPhysicState& state) {
|
||||
if (this != &state) {
|
||||
mId = state.mId;
|
||||
mBaseType = state.mBaseType;
|
||||
mPosition = state.mPosition;
|
||||
mOrientation = state.mOrientation;
|
||||
mVelocity = state.mVelocity;
|
||||
mAngleVelocity = state.mAngleVelocity;
|
||||
mShape = state.mShape->getCopy();
|
||||
mStatic = state.mStatic;
|
||||
mAlive = state.mAlive;
|
||||
mContactNormals = state.mContactNormals;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
vector3d& EntityPhysicState::GetPosition () {
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
vector3d& EntityPhysicState::GetVelocity () {
|
||||
return mVelocity;
|
||||
}
|
||||
|
||||
vector3d& EntityPhysicState::GetOrientation () {
|
||||
return mOrientation;
|
||||
}
|
||||
|
||||
float& EntityPhysicState::GetAngleVelocity () {
|
||||
return mAngleVelocity;
|
||||
}
|
||||
|
||||
void EntityPhysicState::SetPosition (const vector3d &position) {
|
||||
mPosition = position;
|
||||
}
|
||||
|
||||
void EntityPhysicState::SetVelocity (const vector3d &velocity) {
|
||||
mVelocity = velocity;
|
||||
}
|
||||
|
||||
void EntityPhysicState::SetOrientation (const vector3d &orientation) {
|
||||
mOrientation = orientation;
|
||||
}
|
||||
|
||||
void EntityPhysicState::SetAngleVelocity (const float &angle_velocity) {
|
||||
mAngleVelocity = angle_velocity;
|
||||
}
|
||||
|
||||
void EntityPhysicState::Globalize (vector3d &vec) {
|
||||
// make a copy of the local coordinates
|
||||
vector3d local (vec);
|
||||
|
||||
// calculate sin and cos for the current rotation
|
||||
float sintheta, costheta;
|
||||
sintheta = sin (- mOrientation[1] * M_PI / 180);
|
||||
costheta = cos (- mOrientation[1] * M_PI / 180);
|
||||
|
||||
// rotation
|
||||
vec[0] = - sintheta * local[2] + costheta * local[0];
|
||||
vec[1] = local[1];
|
||||
vec[2] = costheta * local[2] + sintheta * local[0] ;
|
||||
|
||||
// and translation
|
||||
vec += mPosition;
|
||||
}
|
||||
|
||||
void EntityPhysicState::Localize (vector3d &vec) {
|
||||
// translation
|
||||
vec -= mPosition;
|
||||
|
||||
vector3d global (vec);
|
||||
|
||||
// calculate sin and cos for the current rotation
|
||||
float sintheta, costheta;
|
||||
sintheta = sin (mOrientation[1] * M_PI / 180);
|
||||
costheta = cos (mOrientation[1] * M_PI / 180);
|
||||
|
||||
// rotation
|
||||
vec[0] = - sintheta * global[2] + costheta * global[0];
|
||||
vec[1] = global[1];
|
||||
vec[2] = costheta * global[2] + sintheta * global[0] ;
|
||||
}
|
||||
|
||||
void EntityPhysicState::GlobalizeRotation (vector3d &vec) {
|
||||
// make a copy of the local coordinates
|
||||
vector3d local (vec);
|
||||
|
||||
// calculate sin and cos for the current rotation
|
||||
float sintheta, costheta;
|
||||
sintheta = sin (- mOrientation[1] * M_PI / 180);
|
||||
costheta = cos (- mOrientation[1] * M_PI / 180);
|
||||
|
||||
// rotation
|
||||
vec[0] = - sintheta * local[2] + costheta * local[0];
|
||||
vec[1] = local[1];
|
||||
vec[2] = costheta * local[2] + sintheta * local[0] ;
|
||||
}
|
||||
|
||||
void EntityPhysicState::LocalizeRotation (vector3d &vec) {
|
||||
vector3d global (vec);
|
||||
|
||||
// calculate sin and cos for the current rotation
|
||||
float sintheta, costheta;
|
||||
sintheta = sin (mOrientation[1] * M_PI / 180);
|
||||
costheta = cos (mOrientation[1] * M_PI / 180);
|
||||
|
||||
// rotation
|
||||
vec[0] = - sintheta * global[2] + costheta * global[0];
|
||||
vec[1] = global[1];
|
||||
vec[2] = costheta * global[2] + sintheta * global[0] ;
|
||||
}
|
||||
|
||||
|
||||
void EntityPhysicState::UpdateShape () {
|
||||
assert (mShape);
|
||||
|
||||
mShape->setPosition (mPosition);
|
||||
mShape->setAngle (mOrientation[1] * M_PI / 180);
|
||||
|
||||
mShape->setVelocity (mVelocity);
|
||||
mShape->setAngleVelocity (mAngleVelocity);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
#include "DrawingsGL.h"
|
||||
#include "OverlayBase.h"
|
||||
#include "SimpleConsoleOverlay.h"
|
||||
|
||||
#include "OGLFT.h"
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
static Variable Var_ConsoleTransparency ("consoletransparency", "0.2");
|
||||
|
||||
bool SimpleConsoleOverlay::OnKeyDown (const SDL_keysym &keysym) {
|
||||
if (keysym.sym == SDLK_F8) {
|
||||
if (mActive) {
|
||||
// We have to call SetActive() to actually
|
||||
// activate the unicode processing of SDL
|
||||
SetActive (false);
|
||||
}
|
||||
else {
|
||||
SetActive (true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!mActive)
|
||||
return false;
|
||||
|
||||
// check for input that requires actions
|
||||
switch (keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
SetActive (false);
|
||||
return true;
|
||||
break;
|
||||
case SDLK_BACKSPACE:
|
||||
if (mCurrentInput.size() > 0)
|
||||
mCurrentInput = mCurrentInput.substr (0, mCurrentInput.size() - 1 );
|
||||
return true;
|
||||
break;
|
||||
case SDLK_RETURN:
|
||||
if (mCurrentInput.size() == 0) {
|
||||
mLastLines.push_back ("");
|
||||
return true;
|
||||
}
|
||||
|
||||
mLastLines.push_back (mCurrentInput);
|
||||
|
||||
// run the command and print out the error if there was one
|
||||
if (!RunCommand (mCurrentInput)) {
|
||||
mLastLines.push_back ("Error: " + CommandGetErrorString());
|
||||
}
|
||||
mCurrentInput = "";
|
||||
return true;
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// if we got input of a character that we can write add it to the current
|
||||
// input
|
||||
if (keysym.unicode) {
|
||||
if ((keysym.unicode & 0xFF80) == 0) {
|
||||
mCurrentInput += keysym.unicode & 0x7F;
|
||||
return true;
|
||||
} else {
|
||||
LogWarning ("Input key not supported!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SimpleConsoleOverlay::Draw () {
|
||||
// we switch to orthographic projection and draw the contents of the 2d
|
||||
// overlay on top of the previous drawings
|
||||
glMatrixMode (GL_PROJECTION);
|
||||
glPushMatrix ();
|
||||
glLoadIdentity ();
|
||||
|
||||
// first we have to get the size of the current viewport to set up the
|
||||
// orthographic projection correctly
|
||||
GLint viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
gluOrtho2D (viewport[0], viewport[2], viewport[3], viewport[1]);
|
||||
|
||||
glMatrixMode (GL_MODELVIEW);
|
||||
glPushMatrix ();
|
||||
glLoadIdentity ();
|
||||
|
||||
// then we do the drawings
|
||||
if (mDrawLogBar)
|
||||
DrawLogBar ();
|
||||
if (mActive)
|
||||
DrawConsole ();
|
||||
|
||||
glPopMatrix ();
|
||||
|
||||
glMatrixMode (GL_PROJECTION);
|
||||
glPopMatrix ();
|
||||
|
||||
glMatrixMode (GL_MODELVIEW);
|
||||
|
||||
};
|
||||
|
||||
void SimpleConsoleOverlay::DrawLogBar () {
|
||||
// first we have to get the size of the current viewport to set up the
|
||||
// orthographic projection correctly
|
||||
GLint viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
|
||||
// we want to enable transparency
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable (GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA);
|
||||
|
||||
float left = 0;
|
||||
float right = static_cast<float> (GetWindowWidth());
|
||||
float top = 0;
|
||||
// float bottom = static_cast<float> (GetWindowHeight());
|
||||
|
||||
// draw the background
|
||||
glColor4f (0.2, 0.2, 0.2, 0.3);
|
||||
glBegin (GL_QUADS);
|
||||
glVertex2f (left, top);
|
||||
glVertex2f (left, top + 16);
|
||||
glVertex2f (right, top + 16);
|
||||
glVertex2f (right, top);
|
||||
glEnd ();
|
||||
|
||||
glDisable (GL_BLEND);
|
||||
|
||||
// draw the log
|
||||
std::ostringstream topbar_stream;
|
||||
topbar_stream << "Log: " << GetLastLogEntry().mMessage;
|
||||
DrawGLString ( 10, 10, topbar_stream.str().c_str ());
|
||||
|
||||
// draw the FPS counter
|
||||
topbar_stream.str ("");
|
||||
topbar_stream << "FPS: " << GetFrameRate();
|
||||
DrawGLString (right - 64 , 10, topbar_stream.str().c_str ());
|
||||
|
||||
glEnable (GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void SimpleConsoleOverlay::DrawConsole () {
|
||||
// first we have to get the size of the current viewport to set up the
|
||||
// orthographic projection correctly
|
||||
GLint viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
|
||||
// we want to enable transparency
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
// glEnable (GL_BLEND);
|
||||
// glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
// glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA);
|
||||
|
||||
// calculate the screen coordinates which defines the size of the
|
||||
// console
|
||||
mLeft = (viewport[2] - viewport[0]) * 0.5 - (viewport[2] - viewport[0]) * 0.45 ;
|
||||
mRight = (viewport[2] - viewport[0]) * 0.5 + (viewport[2] - viewport[0]) * 0.45;
|
||||
mTop = -1; // Do not draw the mTop line
|
||||
mBottom = (viewport[3] - viewport[1]) * 0.7;
|
||||
|
||||
// draw the background
|
||||
glColor4f (0.2, 0.2, 0.2, Var_ConsoleTransparency.GetFloatValue());
|
||||
glBegin (GL_QUADS);
|
||||
glVertex2f (mLeft, mTop);
|
||||
glVertex2f (mLeft, mBottom);
|
||||
glVertex2f (mRight, mBottom);
|
||||
glVertex2f (mRight, mTop);
|
||||
glEnd ();
|
||||
|
||||
// draw borders
|
||||
glColor3f (0.9, 0.9, 0.9);
|
||||
glBegin (GL_LINE_STRIP);
|
||||
glVertex2f (mLeft, mTop);
|
||||
glVertex2f (mLeft, mBottom);
|
||||
glVertex2f (mRight, mBottom);
|
||||
glVertex2f (mRight, mTop);
|
||||
glVertex2f (mLeft, mTop);
|
||||
glEnd ();
|
||||
|
||||
glDisable (GL_BLEND);
|
||||
|
||||
// now draw the contents
|
||||
DrawLastLines ();
|
||||
DrawCurrentInput ();
|
||||
|
||||
glEnable (GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
const std::vector<std::string> SimpleConsoleOverlay::GetLastLines (const unsigned int n) {
|
||||
assert (0);
|
||||
std::vector<std::string> result;
|
||||
return result;
|
||||
}
|
||||
|
||||
void SimpleConsoleOverlay::DrawLastLines () {
|
||||
unsigned int i;
|
||||
for (i = 0; i < mLastLines.size(); i++)
|
||||
DrawGLString (mLeft + 8, mTop + 12 + 12 *i, mLastLines[i].c_str());
|
||||
}
|
||||
|
||||
void SimpleConsoleOverlay::DrawCurrentInput () {
|
||||
// We add a '_' to the current input as a simple cursor
|
||||
static std::string current_input;
|
||||
current_input = mCurrentInput + "_";
|
||||
|
||||
// We add a '>' at the beginning of the input line to highlight it
|
||||
DrawGLString (mLeft, mTop + 12 + 12 * (mLastLines.size()), ">");
|
||||
DrawGLString (mLeft + 8, mTop + 12 + 12 * (mLastLines.size()), current_input.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
#ifndef SIMPLECONSOLEOVERLAY
|
||||
#define SIMPLECONSOLEOVERLAY
|
||||
|
||||
#include "Variables.h"
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
#include <string>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
class OverlayBase;
|
||||
|
||||
class SimpleConsoleOverlay : public OverlayBase {
|
||||
public:
|
||||
SimpleConsoleOverlay () {
|
||||
mActive = false;
|
||||
mDrawLogBar = false;
|
||||
};
|
||||
virtual ~SimpleConsoleOverlay() {};
|
||||
|
||||
virtual bool OnKeyDown (const SDL_keysym &keysym);
|
||||
virtual bool OnKeyUp (const SDL_keysym &keysym) {
|
||||
if(mActive)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
virtual void Draw ();
|
||||
|
||||
void DrawLogBar ();
|
||||
void DrawConsole ();
|
||||
|
||||
/** \brief Returns the last n lines */
|
||||
const std::vector<std::string> GetLastLines (const unsigned int n);
|
||||
/** \brief Returns true if the Console is active */
|
||||
bool GetActive () { return mActive; };
|
||||
/** \brief Activates or deactivates the the Console */
|
||||
void SetActive (bool active) {
|
||||
if (active) {
|
||||
SDL_EnableUNICODE (1);
|
||||
SDL_EnableKeyRepeat (500, 50);
|
||||
}
|
||||
else {
|
||||
SDL_EnableUNICODE (-1);
|
||||
SDL_EnableKeyRepeat (0, 100);
|
||||
}
|
||||
mActive = active;
|
||||
};
|
||||
void SetDrawLogBar (bool value) { mDrawLogBar = value; };
|
||||
|
||||
/** \brief Draws the console with the current content */
|
||||
void DrawLastLines ();
|
||||
void DrawCurrentInput ();
|
||||
|
||||
private:
|
||||
std::vector<std::string> mLastLines;
|
||||
std::string mCurrentInput;
|
||||
bool mActive;
|
||||
bool mDrawLogBar;
|
||||
|
||||
float mLeft;
|
||||
float mTop;
|
||||
float mRight;
|
||||
float mBottom;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* SIMPLECONSOLEOVERLAY */
|
||||
@@ -0,0 +1,237 @@
|
||||
#include "Engine.h"
|
||||
#include "Sprite.h"
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <png.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
/*
|
||||
* Code is taken from http://en.wikibooks.org/wiki/OpenGL_Programming/Intermediate/Textures on
|
||||
* Sunday, March 14 2010.
|
||||
*/
|
||||
bool Sprite::LoadFromPNG (const char *filename) {
|
||||
LogDebug ("Loading png from %s", filename);
|
||||
|
||||
//header for testing if it is a png
|
||||
png_byte header[8];
|
||||
|
||||
//open file as binary
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
if (!fp) {
|
||||
LogError ("Could not open file: %s", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
//read the header
|
||||
fread(header, 1, 8, fp);
|
||||
|
||||
//test if png
|
||||
int is_png = !png_sig_cmp(header, 0, 8);
|
||||
if (!is_png) {
|
||||
LogError ("Error opening png file %s: file is not a png file!", filename);
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
//create png struct
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
|
||||
NULL, NULL);
|
||||
if (!png_ptr) {
|
||||
LogError ("Error opening png file %s: unable to read png header", filename);
|
||||
fclose(fp);
|
||||
return (false);
|
||||
}
|
||||
|
||||
//create png info struct
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr) {
|
||||
LogError ("Error opening png file %s: unable to read png header", filename);
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
|
||||
fclose(fp);
|
||||
return (false);
|
||||
}
|
||||
|
||||
//create png info struct
|
||||
png_infop end_info = png_create_info_struct(png_ptr);
|
||||
if (!end_info) {
|
||||
LogError ("Error opening png file %s: unable to read png header", filename);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
|
||||
fclose(fp);
|
||||
return (false);
|
||||
}
|
||||
|
||||
//png error stuff, not sure libpng man suggests this.
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
LogError ("Error opening png file %s: unable to read png header", filename);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
fclose(fp);
|
||||
return (false);
|
||||
}
|
||||
|
||||
//init png reading
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
//let libpng know you already read the first 8 bytes
|
||||
png_set_sig_bytes(png_ptr, 8);
|
||||
|
||||
// read all the info up to the image data
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
//variables to pass to get info
|
||||
int bit_depth, color_type;
|
||||
png_uint_32 tmWidth, tmHeight;
|
||||
|
||||
// get info about png
|
||||
png_get_IHDR(png_ptr, info_ptr, &tmWidth, &tmHeight, &bit_depth, &color_type,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
//update mWidth and mHeight based on png info
|
||||
mWidth = tmWidth;
|
||||
mHeight = tmHeight;
|
||||
|
||||
// Update the png info struct.
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
|
||||
// Row size in bytes.
|
||||
int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
|
||||
// Allocate the image_data as a big block, to be given to opengl
|
||||
png_byte *image_data = new png_byte[rowbytes * mHeight];
|
||||
if (!image_data) {
|
||||
//clean up memory and close stuff
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
//row_pointers is for pointing to image_data for reading the png with libpng
|
||||
png_bytep *row_pointers = new png_bytep[mHeight];
|
||||
if (!row_pointers) {
|
||||
//clean up memory and close stuff
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
delete[] image_data;
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
// set the individual row_pointers to point at the correct offsets of image_data
|
||||
for (unsigned int i = 0; i < mHeight; ++i)
|
||||
row_pointers[mHeight - 1 - i] = image_data + i * rowbytes;
|
||||
|
||||
//read the png into image_data through row_pointers
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
|
||||
//Now generate the OpenGL texture object
|
||||
glGenTextures(1, &mGlTextureName);
|
||||
glBindTexture(GL_TEXTURE_2D, mGlTextureName);
|
||||
glTexImage2D(GL_TEXTURE_2D,0, GL_RGBA, mWidth, mHeight, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) image_data);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
//clean up memory and close stuff
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
delete[] row_pointers;
|
||||
delete[] image_data;
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Sprite::DrawAt (float xpos, float ypos, float zpos) {
|
||||
float u_start = 0., u_end = 1.;
|
||||
if (mAnimation) {
|
||||
int frame_index = floor ( (mAnimationFrameRate) * mAnimationTimer);
|
||||
u_start = static_cast<float>(frame_index) / mAnimationFrameCount;
|
||||
u_end = (frame_index + 1.) / mAnimationFrameCount;
|
||||
}
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef (xpos -mScale * mWidth * 0.5, ypos, zpos -mScale * mHeight * 0.5);
|
||||
glScalef (mScale, mScale, mScale);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, mGlTextureName);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f (u_start, 0.); glVertex3f (0., 0., 0.);
|
||||
glTexCoord2f (u_end, 0.); glVertex3f (0., 0., mHeight);
|
||||
glTexCoord2f (u_end, 1.); glVertex3f (mWidth, 0., mHeight);
|
||||
glTexCoord2f (u_start, 1.); glVertex3f (mWidth, 0.,0.);
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void Sprite::DrawAt2D (float xpos, float ypos) {
|
||||
float u_start = 0., u_end = 1.;
|
||||
if (mAnimation) {
|
||||
int frame_index = floor ( (mAnimationFrameRate) * mAnimationTimer);
|
||||
u_start = static_cast<float>(frame_index) / mAnimationFrameCount;
|
||||
u_end = (frame_index + 1.) / mAnimationFrameCount;
|
||||
}
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef (xpos -mScale * mWidth * 0.5, ypos, 0.);
|
||||
glScalef (mScale, mScale, mScale);
|
||||
// \TODO Make 2d drawing of sprites a bit nicer, seems a bit overkill for such a simple function
|
||||
glRotatef (-90, 0., 0., 1.);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, mGlTextureName);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f (u_start, 0.); glVertex2f (0., 0.);
|
||||
glTexCoord2f (u_end, 0.); glVertex2f (0., mHeight);
|
||||
glTexCoord2f (u_end, 1.); glVertex2f (mWidth, mHeight);
|
||||
glTexCoord2f (u_start, 1.); glVertex2f (mWidth,0.);
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void Sprite::DrawSubAt (unsigned int index, float xpos, float ypos, float zpos) {
|
||||
assert (index < mSubSpriteCount);
|
||||
|
||||
float u_start = static_cast<float>(index) / mSubSpriteCount;
|
||||
float u_end = (index + 1.) / mSubSpriteCount;
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef (xpos -mScale * mWidth * 0.5, ypos, zpos -mScale * mHeight * 0.5);
|
||||
glScalef (mScale, mScale, mScale);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, mGlTextureName);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f (u_start, 0.); glVertex3f (0., 0., 0.);
|
||||
glTexCoord2f (u_end, 0.); glVertex3f (0., 0., mHeight);
|
||||
glTexCoord2f (u_end, 1.); glVertex3f (mWidth, 0., mHeight);
|
||||
glTexCoord2f (u_start, 1.); glVertex3f (mWidth, 0.,0.);
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef SPRITE_H
|
||||
#define SPRITE_H
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
class Sprite {
|
||||
public:
|
||||
Sprite() {
|
||||
mScale = 1.;
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
mGlTextureName = 0;
|
||||
|
||||
mAnimation = false;
|
||||
mSubSpriteCount = 1;
|
||||
}
|
||||
|
||||
bool LoadFromPNG (const char *filename);
|
||||
void DrawAt (float xpos, float ypos, float zpos);
|
||||
void DrawAt2D (float xpos, float ypos);
|
||||
unsigned int GetWidth() { return mWidth; };
|
||||
unsigned int GetHeight() { return mHeight; };
|
||||
|
||||
void SetScale (float scale) { mScale = scale; };
|
||||
|
||||
void SetAnimation (int frame_count, float frame_rate) {
|
||||
mAnimation = true;
|
||||
mAnimationFrameCount = frame_count;
|
||||
mAnimationFrameRate = frame_rate;
|
||||
mAnimationTimer = 0.;
|
||||
mWidth = static_cast<unsigned int>(ceil (static_cast<float> (mWidth / mAnimationFrameCount)));
|
||||
}
|
||||
void ResetAnimation () {
|
||||
mAnimationTimer = 0.;
|
||||
}
|
||||
void UpdateAnimation (float seconds) {
|
||||
mAnimationTimer += seconds;
|
||||
while (mAnimationTimer >= mAnimationFrameCount / mAnimationFrameRate) {
|
||||
mAnimationTimer -= mAnimationFrameCount / mAnimationFrameRate;
|
||||
}
|
||||
}
|
||||
|
||||
void SetSubSpriteCount (const unsigned int count) {
|
||||
mSubSpriteCount = count;
|
||||
mWidth = static_cast<unsigned int>(ceil (static_cast<float> (mWidth / mSubSpriteCount)));
|
||||
}
|
||||
unsigned int GetSubSpriteCount () const {
|
||||
return mSubSpriteCount;
|
||||
}
|
||||
void DrawSubAt (unsigned int index, float xpos, float ypos, float zpos);
|
||||
|
||||
private:
|
||||
float mScale;
|
||||
|
||||
unsigned int mWidth;
|
||||
unsigned int mHeight;
|
||||
unsigned int mGlTextureName;
|
||||
|
||||
unsigned int mSubSpriteCount;
|
||||
|
||||
bool mAnimation;
|
||||
int mAnimationFrameCount;
|
||||
float mAnimationTimer;
|
||||
float mAnimationFrameRate;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* SPRITE_H */
|
||||
@@ -0,0 +1,159 @@
|
||||
#include "Variables.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
Variables* VariablesInstance = NULL;
|
||||
|
||||
/*
|
||||
* Inherited Module functions
|
||||
*/
|
||||
int Variables::OnInit (int argc, char* argv[]) {
|
||||
LogDebug ("Variables Init");
|
||||
|
||||
VariablesInstance = this;
|
||||
|
||||
/* This definition of a variable causes the delayed variables to be loaded,
|
||||
* please keep it here! */
|
||||
static Variable VariableSystemUp_var ("variablesystemup", "true");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Variables::OnDestroy () {
|
||||
LogDebug ("Variables Destroy");
|
||||
|
||||
VariablesInstance = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Module specific functions
|
||||
*/
|
||||
void Variables::RegisterVariable (const std::string &name, Variable *var) {
|
||||
LogDebug ("Registering Variable '%s'", name.c_str ());
|
||||
if (mVariablesData.find (name) != mVariablesData.end()) {
|
||||
// Variable already existing!
|
||||
mVariablesData[name] = var;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
mVariablesData[name] = var;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Variable class
|
||||
*/
|
||||
Variable* Variables::GetVariable (const std::string &name) {
|
||||
if (mVariablesData.find (name) == mVariablesData.end()) {
|
||||
// Variable not existing!
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mVariablesData[name];
|
||||
}
|
||||
|
||||
Variable::Variable (const std::string &name, const std::string &value) {
|
||||
static std::vector<Variable*> delayed_variables;
|
||||
|
||||
mName = name;
|
||||
mStringValue = value;
|
||||
mFloatValue = atof (value.c_str());
|
||||
|
||||
if (VariablesInstance == NULL) {
|
||||
delayed_variables.push_back (this);
|
||||
} else if (delayed_variables.size() > 0) {
|
||||
LogDebug ("Loading delayed Variables");
|
||||
unsigned int i;
|
||||
for (i = 0; i < delayed_variables.size(); i ++)
|
||||
VariablesInstance->RegisterVariable (delayed_variables[i]->mName, delayed_variables[i]);
|
||||
|
||||
delayed_variables.clear ();
|
||||
|
||||
RegisterVariable (name);
|
||||
} else {
|
||||
RegisterVariable (name);
|
||||
}
|
||||
}
|
||||
|
||||
void Variable::RegisterVariable (const std::string &name) {
|
||||
if (! VariablesInstance ) {
|
||||
LogError ("Unable to register Variable '%s': Variables System not initialized!", name.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
VariablesInstance->RegisterVariable (name, this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Global functions
|
||||
*/
|
||||
Variable* GetVariable (const std::string &name) {
|
||||
if (! VariablesInstance ) {
|
||||
LogError ("Unable to register Variable '%s': Variables System not initialized!", name.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return VariablesInstance->GetVariable (name);
|
||||
}
|
||||
|
||||
bool SetVariableValue (const std::string &name, const std::string value) {
|
||||
if (! VariablesInstance ) {
|
||||
LogError ("Unable to set Variable '%s': Variables System not initialized!", name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
Variable *var = VariablesInstance->GetVariable (name);
|
||||
if (!var) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var->SetStringValue (value);
|
||||
var->SetFloatValue (atof (value.c_str()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string& GetVariableString (const std::string &name, std::string def) {
|
||||
/* We use a static result variable for the case that def was not passed to
|
||||
* is function */
|
||||
static std::string def_result = def;
|
||||
|
||||
if (! VariablesInstance ) {
|
||||
LogError ("Unable to register Variable '%s': Variables System not initialized!", name.c_str());
|
||||
return def_result;
|
||||
}
|
||||
|
||||
Variable *var = VariablesInstance->GetVariable (name);
|
||||
if (!var) {
|
||||
return def_result;
|
||||
}
|
||||
|
||||
return var->GetStringValue ();
|
||||
}
|
||||
|
||||
float &GetVariableFloat (const std::string &name, float def) {
|
||||
/* We use a static result variable for the case that def was not passed to
|
||||
* is function */
|
||||
static float def_result = def;
|
||||
|
||||
if (! VariablesInstance ) {
|
||||
LogError ("Unable to register Variable '%s': Variables System not initialized!", name.c_str());
|
||||
return def_result;
|
||||
}
|
||||
|
||||
Variable *var = VariablesInstance->GetVariable (name);
|
||||
if (!var) {
|
||||
return def_result;
|
||||
}
|
||||
|
||||
return var->GetFloatValue ();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef _VARIABLES_H
|
||||
#define _VARIABLES_H
|
||||
|
||||
#include "Engine.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
class Module;
|
||||
class Variable;
|
||||
|
||||
/** \brief Manages all variables that can be changed by the Model itself
|
||||
*
|
||||
* \todo make the variable names case insensitive
|
||||
* \todo only allow certain characters in variable names
|
||||
*/
|
||||
class Variables : public Module{
|
||||
public:
|
||||
void RegisterVariable (const std::string &name, Variable *var);
|
||||
Variable *GetVariable (const std::string &name);
|
||||
|
||||
protected:
|
||||
/** \brief Initializes the system */
|
||||
int OnInit (int argc, char* argv[]);
|
||||
/** \brief Destroys the system (must be called!) */
|
||||
void OnDestroy ();
|
||||
void OnRegisterCommands ();
|
||||
|
||||
std::map<std::string, Variable*> mVariablesData;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _VARIABLES_H
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "Variables.h"
|
||||
|
||||
namespace Engine {
|
||||
|
||||
bool Cmd_Set (const std::vector<std::string> args) {
|
||||
if (args.size() != 2) {
|
||||
CommandSetErrorString ("Usage: set <name> <value>\nSets variables <name> to value <value>.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Variable *test = GetVariable (args[0]);
|
||||
if (test) {
|
||||
test->SetStringValue (args[1]);
|
||||
test->SetFloatValue (atof (args[1].c_str()));
|
||||
return true;
|
||||
}
|
||||
|
||||
CommandSetErrorString ("Variable '" + args[0] +"' not found!");
|
||||
return false;
|
||||
}
|
||||
|
||||
void Variables::OnRegisterCommands () {
|
||||
AddCommand ("set", Cmd_Set);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
#ifndef _VARIABLESGLOBAL_H
|
||||
#define _VARIABLESGLOBAL_H
|
||||
|
||||
namespace Engine {
|
||||
/** \brief Represents a variable that can be modified and read within the game
|
||||
*
|
||||
* \note Variables \b MUST be declared as static variables, otherwise the memory that
|
||||
* hold their values get invalidated and the system gets unstable!
|
||||
*/
|
||||
class Variable {
|
||||
public:
|
||||
/** \brief The constructor to be used when initializing a Variable
|
||||
*
|
||||
* \param name The name under which the variable is engine wide
|
||||
* accessible
|
||||
* \param value The value it is assigned to.
|
||||
*
|
||||
* The value string gets automatically converted to a float with atof ().
|
||||
* Modification of a Variable must always be made with the Get*, Set*
|
||||
* functions.
|
||||
*/
|
||||
Variable (const std::string &name, const std::string &value);
|
||||
|
||||
/** \brief Returns the string value of the Variable */
|
||||
std::string& GetStringValue () {
|
||||
return mStringValue;
|
||||
}
|
||||
/** \brief Returns the float value of the Variable */
|
||||
float& GetFloatValue () {
|
||||
return mFloatValue;
|
||||
}
|
||||
void SetStringValue (const std::string &value) {
|
||||
mStringValue = value;
|
||||
}
|
||||
void SetFloatValue (float value) {
|
||||
mFloatValue = value;
|
||||
}
|
||||
|
||||
private:
|
||||
/** \brief The default constructor must not be used.
|
||||
*
|
||||
* Use \code
|
||||
* Variable (const std::string &name, const std::string &value)
|
||||
* \endcode
|
||||
* instead.
|
||||
* */
|
||||
Variable () { assert (0); }
|
||||
/** \brief Registeres this Variable with the Variables System */
|
||||
void RegisterVariable (const std::string &name);
|
||||
|
||||
std::string mName;
|
||||
std::string mStringValue;
|
||||
float mFloatValue;
|
||||
|
||||
friend class Variables;
|
||||
};
|
||||
|
||||
/** \brief Provides access to a Variable stored under the given name */
|
||||
Variable* GetVariable (const std::string &name);
|
||||
/** \brief Sets the vaule of the Variable */
|
||||
bool SetVariableValue (const std::string &name, const std::string &value);
|
||||
/** \brief Returns the string value of the Variable with the given name */
|
||||
std::string& GetVariableString (const std::string &name, std::string def = "");
|
||||
/** \brief Returns the float value of the Variable with the given name */
|
||||
float& GetVariableFloat (const std::string &name, float def = 0.);
|
||||
|
||||
}
|
||||
#endif // _VARIABLESGLOBAL_H
|
||||
@@ -0,0 +1,330 @@
|
||||
#include "ViewBase.h"
|
||||
|
||||
#include "ModelBase.h"
|
||||
#include "ControllerBase.h"
|
||||
#include "CameraBase.h"
|
||||
#include "OverlayBase.h"
|
||||
|
||||
#include "SimpleConsoleOverlay.h"
|
||||
#include "OGLFT.h"
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
|
||||
#include "DrawingsGL.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Engine {
|
||||
|
||||
static ViewBase* ViewInstance = NULL;
|
||||
|
||||
void InitGL () {
|
||||
glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
|
||||
glClearDepth(1.0);
|
||||
glDepthFunc(GL_LESS);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glEnable (GL_CULL_FACE);
|
||||
glDisable (GL_FOG);
|
||||
|
||||
glMatrixMode (GL_PROJECTION);
|
||||
glLoadIdentity ();
|
||||
glMatrixMode (GL_MODELVIEW);
|
||||
glLoadIdentity ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Inherited Module functions
|
||||
*/
|
||||
int ViewBase::OnInit (int argc, char* argv[]) {
|
||||
LogMessage ("View Init");
|
||||
|
||||
mWindowHeight = VIEW_DEFAULT_HEIGHT;
|
||||
mWindowWidth = VIEW_DEFAULT_WIDTH;
|
||||
|
||||
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
|
||||
|
||||
if( SDL_SetVideoMode( mWindowWidth, mWindowHeight, 16, SDL_OPENGL | SDL_RESIZABLE ) == 0 ) {
|
||||
LogError ("Video mode set failed: %s", SDL_GetError ());
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
InitGL ();
|
||||
Resize (mWindowWidth, mWindowHeight);
|
||||
|
||||
mConsoleFont = new OGLFT::Monochrome ("./data/fonts/console.ttf", 12);
|
||||
|
||||
if ( mConsoleFont == 0 || !mConsoleFont->isValid() ) {
|
||||
LogError ("Could not load font %s!", "./data/fonts/console.ttf");
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
SimpleConsoleOverlay* console_overlay = new SimpleConsoleOverlay;
|
||||
AddOverlay (console_overlay);
|
||||
|
||||
mConsoleFont->setForegroundColor (1., 1., 1.);
|
||||
|
||||
mDrawAxis = false;
|
||||
|
||||
mDrawGrid = false;
|
||||
mGridSizeX = 8;
|
||||
mGridSizeZ = 8;
|
||||
|
||||
ViewInstance = this;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ViewBase::OnDestroy () {
|
||||
if (mConsoleFont )
|
||||
delete mConsoleFont;
|
||||
mConsoleFont = NULL;
|
||||
|
||||
std::vector<OverlayBase*>::iterator overlay_iter = mOverlays.begin(), overlay_temp;
|
||||
while (overlay_iter != mOverlays.end()) {
|
||||
overlay_temp = overlay_iter;
|
||||
delete *overlay_temp;
|
||||
|
||||
overlay_iter++;
|
||||
}
|
||||
|
||||
ViewInstance = NULL;
|
||||
|
||||
LogDebug ("View Destroy");
|
||||
}
|
||||
|
||||
void ViewBase::CalcWorldCoordinates (int screen_x, int screen_y, float world_y, float *pos_out) {
|
||||
GLdouble modelMatrix[16], projMatrix[16];
|
||||
GLint viewport[4];
|
||||
GLdouble wx, wy, wz;
|
||||
|
||||
glGetIntegerv (GL_VIEWPORT, viewport);
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
|
||||
glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
|
||||
|
||||
int realy = viewport[3] - screen_y - 1;
|
||||
|
||||
gluUnProject ((GLdouble) screen_x, (GLdouble) realy, 1.,
|
||||
modelMatrix, projMatrix, viewport, &wx, &wy, &wz);
|
||||
|
||||
GLdouble t;
|
||||
GLdouble d[3];
|
||||
float eye[3];
|
||||
|
||||
mCamera->GetEye (&eye[0]);
|
||||
|
||||
d[0] = wx - eye[0];
|
||||
d[1] = wy - eye[1];
|
||||
d[2] = wz - eye[2];
|
||||
|
||||
assert (fabs (d[1]) >= 1.0e-3);
|
||||
t = -eye[1]/d[1] + world_y;
|
||||
|
||||
pos_out[0] = eye[0] + t * d[0];
|
||||
pos_out[1] = eye[1] + t * d[1];
|
||||
pos_out[2] = eye[2] + t * d[2];
|
||||
}
|
||||
|
||||
/*
|
||||
* Module specific functions
|
||||
*/
|
||||
void ViewBase::UpdateCamera () {
|
||||
EntityPhysicState* player_ent = GetEntityPhysicState (GetPlayerEntityId());
|
||||
|
||||
if (!player_ent) {
|
||||
LogError ("Could not call Model::PositionCamera(): player entity not found!");
|
||||
exit (-1);
|
||||
}
|
||||
vector3d entity_camera_distance (-2, 3, 0);
|
||||
vector3d entity_position = player_ent->GetPosition();
|
||||
player_ent->Globalize (entity_camera_distance);
|
||||
|
||||
mCamera->SetEye (
|
||||
entity_camera_distance[0],
|
||||
entity_camera_distance[1],
|
||||
entity_camera_distance[2]
|
||||
);
|
||||
mCamera->SetPointOfIntrest (
|
||||
entity_position[0],
|
||||
entity_position[1],
|
||||
entity_position[2]
|
||||
);
|
||||
|
||||
mCamera->Update ();
|
||||
}
|
||||
|
||||
void ViewBase::Draw () {
|
||||
// Clear the screen
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// update the frame rate counter
|
||||
static Uint32 this_frame_ticks;
|
||||
static Uint32 last_frame_ticks = 0;
|
||||
static Uint32 last_fps_update = 0;
|
||||
static int frame_counter = 0;
|
||||
|
||||
this_frame_ticks = SDL_GetTicks ();
|
||||
last_fps_update += this_frame_ticks - last_frame_ticks;
|
||||
last_frame_ticks = this_frame_ticks;
|
||||
frame_counter++;
|
||||
|
||||
if (last_fps_update > 1000) {
|
||||
mFrameRate = frame_counter;
|
||||
last_fps_update = 0;
|
||||
frame_counter = 0;
|
||||
}
|
||||
|
||||
UpdateCamera ();
|
||||
|
||||
if (mDrawGrid)
|
||||
DrawGrid ();
|
||||
|
||||
if (mDrawAxis)
|
||||
DrawAxis ();
|
||||
|
||||
DrawWorld ();
|
||||
|
||||
std::vector<OverlayBase*>::iterator overlay_iter;
|
||||
for (overlay_iter = mOverlays.begin(); overlay_iter != mOverlays.end(); overlay_iter++) {
|
||||
(*overlay_iter)->Draw();
|
||||
}
|
||||
|
||||
// and update the screen
|
||||
SDL_GL_SwapBuffers ();
|
||||
}
|
||||
|
||||
void ViewBase::DrawGLString (float x, float y, const char* str) {
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
|
||||
mConsoleFont->draw (x, y, str);
|
||||
}
|
||||
|
||||
void ViewBase::GetCamereEye (float *eye_out) {
|
||||
assert (mCamera);
|
||||
mCamera->GetEye (eye_out);
|
||||
}
|
||||
|
||||
void ViewBase::DrawGrid () {
|
||||
float xmin, xmax, xstep, zmin, zmax, zstep;
|
||||
int i, count_x, count_z;
|
||||
|
||||
xmin = -mGridSizeX;
|
||||
xmax = mGridSizeX;
|
||||
zmin = -mGridSizeZ;
|
||||
zmax = mGridSizeZ;
|
||||
|
||||
count_x = mGridSizeX * 2;
|
||||
count_z = mGridSizeZ * 2;
|
||||
|
||||
xstep = 1.;
|
||||
zstep = 1.;
|
||||
|
||||
glColor3f (1., 1., 1.);
|
||||
glBegin (GL_LINES);
|
||||
for (i = 0; i <= count_x; i++) {
|
||||
glVertex3f (i * xstep + xmin, 0., zmin);
|
||||
glVertex3f (i * xstep + xmin, 0., zmax);
|
||||
}
|
||||
for (i = 0; i <= count_z; i++) {
|
||||
glVertex3f (xmin, 0, i * zstep + zmin);
|
||||
glVertex3f (xmax, 0, i * zstep + zmin);
|
||||
}
|
||||
glEnd ();
|
||||
|
||||
}
|
||||
|
||||
void ViewBase::DrawWorld () {
|
||||
}
|
||||
|
||||
void ViewBase::Resize (int width, int height) {
|
||||
if (height == 0)
|
||||
height = 1;
|
||||
|
||||
mWindowWidth = static_cast<unsigned int> (width);
|
||||
mWindowHeight = static_cast<unsigned int> (height);
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective(mCamera->GetFOVY (), float (width) / float (height), 0.1, 100);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity ();
|
||||
|
||||
LogDebug ("Resize to: %d x %d", mWindowWidth,mWindowHeight);
|
||||
|
||||
/** \warning
|
||||
* This call has to be made for SDL 1.2 for 1.3 there seems to be a
|
||||
* workaround, however since I do not yet run SDL 1.3 I hold on to this.
|
||||
* See http://lists.libsdl.org/pipermail/sdl-libsdl.org/2008-November/067306.html
|
||||
*/
|
||||
if( SDL_SetVideoMode( mWindowWidth, mWindowHeight, 16, SDL_OPENGL | SDL_RESIZABLE ) == 0 ) {
|
||||
LogError ("Video mode set failed: %s", SDL_GetError ());
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
|
||||
bool ViewBase::SendKeyDown (const SDL_keysym &keysym) {
|
||||
std::vector<OverlayBase*>::iterator overlay_iter;
|
||||
for (overlay_iter = mOverlays.begin(); overlay_iter != mOverlays.end(); overlay_iter++) {
|
||||
if ( (*overlay_iter)->OnKeyDown (keysym))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ViewBase::SendKeyUp (const SDL_keysym &keysym) {
|
||||
std::vector<OverlayBase*>::iterator overlay_iter;
|
||||
for (overlay_iter = mOverlays.begin(); overlay_iter != mOverlays.end(); overlay_iter++) {
|
||||
if ( (*overlay_iter)->OnKeyUp (keysym))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ViewBase::SendMouseButtonUp (Uint8 button, Uint16 xpos, Uint16 ypos) {
|
||||
std::vector<OverlayBase*>::iterator overlay_iter;
|
||||
for (overlay_iter = mOverlays.begin(); overlay_iter != mOverlays.end(); overlay_iter++) {
|
||||
if ( (*overlay_iter)->OnMouseButtonUp (button, xpos, ypos))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ViewBase::SendMouseButtonDown (Uint8 button, Uint16 xpos, Uint16 ypos) {
|
||||
std::vector<OverlayBase*>::iterator overlay_iter;
|
||||
for (overlay_iter = mOverlays.begin(); overlay_iter != mOverlays.end(); overlay_iter++) {
|
||||
if ( (*overlay_iter)->OnMouseButtonDown (button, xpos, ypos))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Global functions
|
||||
*/
|
||||
void DrawGLString (float x, float y, const char* str) {
|
||||
if (!ViewInstance) {
|
||||
LogError ("Cannot Draw GL String: View not yet initialized!");
|
||||
return;
|
||||
}
|
||||
ViewInstance->DrawGLString (x, y, str);
|
||||
}
|
||||
|
||||
unsigned int GetWindowWidth() {
|
||||
return ViewInstance->GetWindowWidth ();
|
||||
}
|
||||
|
||||
unsigned int GetWindowHeight() {
|
||||
return ViewInstance->GetWindowHeight ();
|
||||
}
|
||||
|
||||
int GetFrameRate () {
|
||||
return ViewInstance->GetFrameRate ();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#ifndef _VIEWBASE_H
|
||||
#define _VIEWBASE_H
|
||||
|
||||
#include "Engine.h"
|
||||
|
||||
// forward declarations for the OGLFT fonts
|
||||
namespace OGLFT {
|
||||
class Monochrome;
|
||||
}
|
||||
|
||||
namespace Engine {
|
||||
|
||||
class Module;
|
||||
class ModelBase;
|
||||
class CameraBase;
|
||||
class OverlayBase;
|
||||
|
||||
/** \brief Performs the actual drawing based on Camera and Model
|
||||
*/
|
||||
|
||||
class ViewBase : public Module{
|
||||
public:
|
||||
/** \brief Resizes the View */
|
||||
void Resize (int width, int height);
|
||||
|
||||
/** \brief Performs all drawing */
|
||||
virtual void Draw ();
|
||||
|
||||
/** \brief Draws a string at the given position using current projection
|
||||
* and modelview matrices */
|
||||
void DrawGLString (float x, float y, const char* str);
|
||||
/** \brief Stores the eye poisition in eye_out */
|
||||
void GetCamereEye (float *eye_out);
|
||||
|
||||
/** \brief Calculates the world coordinates to given screen coordinates */
|
||||
void CalcWorldCoordinates (int screen_x, int screen_y, float world_y, float *pos_out);
|
||||
|
||||
unsigned int GetWindowWidth () { return mWindowWidth; };
|
||||
unsigned int GetWindowHeight () { return mWindowHeight; };
|
||||
int GetFrameRate() { return mFrameRate; };
|
||||
|
||||
void SetDrawAxis (bool draw_axis) { mDrawGrid = draw_axis; };
|
||||
bool GetDrawAxis () { return mDrawGrid; };
|
||||
void SetDrawGrid (bool draw_grid) { mDrawGrid = draw_grid; };
|
||||
bool GetDrawGrid () { return mDrawGrid; };
|
||||
void SetGridSize (int x, int z) { mGridSizeX = x; mGridSizeZ = z; }
|
||||
|
||||
void AddOverlay (OverlayBase *overlay) { mOverlays.push_back (overlay); };
|
||||
|
||||
/* Input forwarding for the overlays */
|
||||
bool SendKeyDown (const SDL_keysym &keysym);
|
||||
bool SendKeyUp (const SDL_keysym &keysym);
|
||||
bool SendMouseButtonUp (Uint8 button, Uint16 xpos, Uint16 ypos);
|
||||
bool SendMouseButtonDown (Uint8 button, Uint16 xpos, Uint16 ypos);
|
||||
|
||||
protected:
|
||||
/** \brief Initializes the system */
|
||||
int OnInit (int argc, char* argv[]);
|
||||
/** \brief Destroys the system (must be called!) */
|
||||
void OnDestroy ();
|
||||
|
||||
/** \brief Updates the camera for further drawing */
|
||||
virtual void UpdateCamera ();
|
||||
/** \brief Draws a grid of 16 x 16 tiles */
|
||||
void DrawGrid ();
|
||||
/** \brief Draws the level and all the visible Entities */
|
||||
virtual void DrawWorld ();
|
||||
/** \brief Draws orthographic overlay*/
|
||||
void DrawOverlay2D ();
|
||||
|
||||
ModelBase *mModel;
|
||||
CameraBase *mCamera;
|
||||
|
||||
std::vector<OverlayBase*> mOverlays;
|
||||
|
||||
/** \brief The height of the canvas we're drawing on */
|
||||
unsigned int mWindowHeight;
|
||||
/** \brief The width of the canvas we're drawing on */
|
||||
unsigned int mWindowWidth;
|
||||
/** \brief Stores the current frame rate */
|
||||
int mFrameRate;
|
||||
|
||||
bool mDrawAxis;
|
||||
bool mDrawGrid;
|
||||
int mGridSizeX;
|
||||
int mGridSizeZ;
|
||||
|
||||
/** \brief Font that is used in the console */
|
||||
OGLFT::Monochrome* mConsoleFont;
|
||||
|
||||
friend class Engine;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include "ViewBaseGlobal.h"
|
||||
|
||||
#endif // _VIEWBase_H
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef _VIEWGLOBAL_H
|
||||
#define _VIEWGLOBAL_H
|
||||
|
||||
namespace Engine {
|
||||
|
||||
/** \brief Draws the given string at the given position using the current
|
||||
* OpenGL transformations */
|
||||
void DrawGLString (float x, float y, const char* str);
|
||||
|
||||
unsigned int GetWindowWidth();
|
||||
unsigned int GetWindowHeight();
|
||||
|
||||
int GetFrameRate ();
|
||||
|
||||
}
|
||||
|
||||
#endif /* _VIEWGLOBAL_H */
|
||||
@@ -0,0 +1,72 @@
|
||||
#include "EntityBase.h"
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
void EntityVisualState::Draw () {
|
||||
if (mBaseType == EntityBaseTypeActor) {
|
||||
int i, segments;
|
||||
segments = 20;
|
||||
double x, z, rad, drad;
|
||||
|
||||
drad = (M_PI * 2) / segments;
|
||||
|
||||
glBegin (GL_TRIANGLE_FAN);
|
||||
glVertex3f (0., 0., 0.);
|
||||
for (i = 0; i <= segments; i++) {
|
||||
rad = drad * i;
|
||||
sincos (rad, &z, &x);
|
||||
glVertex3f (x * mRadius, 0., -z * mRadius);
|
||||
}
|
||||
glEnd ();
|
||||
|
||||
glDisable (GL_DEPTH_TEST);
|
||||
glColor3f (0.8, 0., 0.2);
|
||||
glBegin (GL_TRIANGLES);
|
||||
glVertex3f (mRadius, 0., 0.);
|
||||
glVertex3f (0., 0., -mRadius * 0.3);
|
||||
glVertex3f (0., 0., mRadius * 0.3);
|
||||
glEnd ();
|
||||
glEnable (GL_DEPTH_TEST);
|
||||
|
||||
return;
|
||||
} else if (mBaseType == EntityBaseTypeBlock) {
|
||||
glBegin (GL_QUADS);
|
||||
glVertex3f (-0.5, 0., 0.5);
|
||||
glVertex3f (0.5, 0., 0.5);
|
||||
glVertex3f (0.5, 0., -0.5);
|
||||
glVertex3f (-0.5, 0., -0.5);
|
||||
glEnd ();
|
||||
} else if (mBaseType == EntityBaseTypeParticle) {
|
||||
int i, segments;
|
||||
segments = 20;
|
||||
double x, z, rad, drad;
|
||||
|
||||
drad = (M_PI * 2) / segments;
|
||||
|
||||
glDisable (GL_DEPTH_TEST);
|
||||
glColor3f (0., 0.8, 0.1);
|
||||
glBegin (GL_TRIANGLE_FAN);
|
||||
glVertex3f (0., 0., 0.);
|
||||
for (i = 0; i <= segments; i++) {
|
||||
rad = drad * i;
|
||||
sincos (rad, &z, &x);
|
||||
glVertex3f (x * mRadius, 0., -z * mRadius);
|
||||
}
|
||||
glEnd ();
|
||||
|
||||
glColor3f (0.8, 0., 0.2);
|
||||
glBegin (GL_TRIANGLES);
|
||||
glVertex3f (mRadius, 0., 0.);
|
||||
glVertex3f (0., 0., -mRadius * 0.3);
|
||||
glVertex3f (0., 0., mRadius * 0.3);
|
||||
glEnd ();
|
||||
glEnable (GL_DEPTH_TEST);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/** \file documentation.h \mainpage Main Page
|
||||
*
|
||||
* This is the documentation of Engine -- a game engine without a name.
|
||||
*
|
||||
* \section General Information
|
||||
*
|
||||
* To get an overview over the most important functions and classes have a
|
||||
* look at Engine. For the structure of the Engine look at Engine::Engine. In
|
||||
* \ref usecases you find documentation on how things are supposed to work and
|
||||
* what the ideas behind certain designs is.
|
||||
*
|
||||
* \section Physics
|
||||
*
|
||||
* So far we only use a very simple physics system which is mostly defined by
|
||||
* the Engine::Physics class. It uses the coll2d collision library. Collision
|
||||
* response so far only tries to prevent interpenetration.
|
||||
*
|
||||
* \section Networking
|
||||
*
|
||||
* For easier networking it is assumed that everything runs over a network.
|
||||
* The game itself is rather a smart client to a simple synchronization
|
||||
* protocol. What is being synchronized is the game state and the client
|
||||
* simply displays the current state it knows. The client is "smart" as it
|
||||
* tries to guess what the next state will be.
|
||||
*
|
||||
* For networking we want to use Enet http://enet.bespin.org/.
|
||||
*
|
||||
* Notes for networking: At
|
||||
* http://www.gamedev.net/community/forums/topic.asp?topic_id=550962 is an
|
||||
* interesting thread about modeling the updates. Especially the answer of
|
||||
* Antheus at http://www.gamedev.net/community/forums/viewreply.asp?ID=3546077
|
||||
* describes two fundamental models:
|
||||
*
|
||||
* Level Triggering (GoF Observer Pattern): Entity A sends its changes to the
|
||||
* Observer pattern and all objects that are interested in the state of Entity
|
||||
* A get notfied by the observer.
|
||||
*
|
||||
* Edge Triggering: For each Entity A the Observer B is interested, it stores
|
||||
* a flag for a value it is interested in (e.g. one for position, one for
|
||||
* velocity, etc.). When Entity A modifies one of the values it notifies the
|
||||
* observer that its current state has changed and the Observer sets the flag
|
||||
* to "dirty". Anyone interested in events polls at the Observer and decides
|
||||
* what to do with it. When the value is queried, the Observer reads the value
|
||||
* from the Entity and clears the flag.
|
||||
*
|
||||
* For networking a combination can be used: During the simulation loop only
|
||||
* Edge Triggering is performed and at the end of it, all dirty States get
|
||||
* sent over the network.
|
||||
*
|
||||
* When notifying events such as "Add new Entity X" the user tomv describes at
|
||||
* http://www.gamedev.net/community/forums/viewreply.asp?ID=3545586 a method
|
||||
* to circumvent these messages. Instead, the server simply sends out updates
|
||||
* about the Entities around a player where close Entities are updated more
|
||||
* frequently than ones that are further away. It simply sends "Entity X
|
||||
* changed by D". If a client does not know what the Entity X is, it queries
|
||||
* the type and current state of the Entity X and therefore reconstructs the
|
||||
* surroundings step-by-step. It is also robust against dropped messages of
|
||||
* the form "Add new Entity X".
|
||||
*
|
||||
* At tomvas model there are some problems: How are events "Delete Entity X"
|
||||
* handled? How to handle malicious clients that request the state of all
|
||||
* Entities? (Solution for the last question: Request Queues).
|
||||
*
|
||||
* Kylotan cals tomvas model as a unreliable system for generic state
|
||||
* [synchronization?] (http://www.gamedev.net/community/forums/viewreply.asp?ID=3548662).
|
||||
* Additionally he mentions that it can increase occurences of short term
|
||||
* unsynchronous states and reccomends using some reliable message passing.
|
||||
*
|
||||
* \section ToDos
|
||||
*
|
||||
* This is a loose list of items that are to be implemented. For a list of all
|
||||
* todos within the code have a look at the \ref todo.
|
||||
*
|
||||
* \todo [high] Create a simple racing or asteroids game
|
||||
* \todo [med] Clear all references of EntityVisualState and EntityGameState
|
||||
* \todo [med] Clarify functionalities of CreateEntity, KillEntity, RegisterEntity, UnregisterEntity (which frees memory, which does only change the state of the Model?)
|
||||
* \todo [med] Add basic networking
|
||||
* \todo [med] Add serialization
|
||||
* \todo [med] Add cal3d support
|
||||
* \todo [med] Smooth Physics at convex collisions (somehow there is jitter)
|
||||
* \todo [med] Create better collsion response
|
||||
* \todo [med] In rare cases two Actors can penetrate each other (probably at slow velocities)
|
||||
* \todo [low] Add a timer object to keep track of what is sucking performance.
|
||||
* \todo [low] Add a inspector widget that shows information about a selected Entity
|
||||
* \todo [low] Use a std::map<string, string> as initialization parameters for
|
||||
* Engine::Module::Init()
|
||||
*
|
||||
* Done:
|
||||
* - [high] In Physics remove dependancy on the Model to pass on collision
|
||||
* events
|
||||
* - [high] Fix Physics bug when two actors collide actively (i.e. velocity
|
||||
* towards each other)
|
||||
* - [med] Better Game Input so that each Entity has its own ControllerState
|
||||
* that can be modified
|
||||
* - [med] (31-01-2009) Add support for loading levels (and saving!)
|
||||
*/
|
||||
@@ -0,0 +1,114 @@
|
||||
/** \page usecases Usecases
|
||||
*
|
||||
* This page contains some information on how various tasks are supposed to be
|
||||
* performed with this engine. It should help understand how the internals
|
||||
* work and how to avoid certain pitfalls.
|
||||
*
|
||||
* \section entity_management Entity Management
|
||||
*
|
||||
* Entities have to be created with Engine::CreateEntity() Factory Method.
|
||||
* This will also cause the correct registration in all modules (especially in
|
||||
* the Engine::Physics module). And create the registrations for it.
|
||||
*
|
||||
* Once an Entity is no more used, one has to call Engine::DestroyEntity().
|
||||
*
|
||||
* \section entitiy_drawing Drawing of an Entity
|
||||
*
|
||||
* Aim: The visual state must always represent the visual state of the game
|
||||
* state.
|
||||
*
|
||||
* To do this we always have to update the visual entity from the game state
|
||||
* entity.
|
||||
*
|
||||
* \code
|
||||
* View::DrawEntity (Entity* entity) {
|
||||
* // if this entity has no visual part we don't need to draw
|
||||
* if (! entity->mPhysicState) return;
|
||||
*
|
||||
* // update entity->mVisualState based on entity->mGameState
|
||||
*
|
||||
* // perform positioning based on entity->mPhysicState
|
||||
*
|
||||
* // perform drawing based on entity->mVisualState
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \section game_input Game Input
|
||||
*
|
||||
* Each Entity has a ControllerState which keeps track on how the Entity is
|
||||
* currently steered. This is then processed by the model each frame for each
|
||||
* entity and updates the velocities / orientations etc. before the physical
|
||||
* simulation is started. The player input simply forwards its input to the
|
||||
* Entity with the Player Id and updates the ControllerState of the Entity
|
||||
* with the Id.
|
||||
*
|
||||
* To add a new key state one has to follow these steps:
|
||||
* - add a new EntityControllerKeyState e.g. EntityKeyStateCrouch (must be added
|
||||
* above EntityKeyStateLast)
|
||||
* - define the behaviour of the control in Entity::ProcessController() which
|
||||
* updates the EntityPhysicalState of the Entity
|
||||
* - add a command to be able to bind a key to the EntityControllerKeyState
|
||||
*
|
||||
* \section console_input Console Input
|
||||
*
|
||||
* Since it could be that the key being pressed has to be forwarded to another
|
||||
* system such as the Menu or the Engine::Console system, we have to query the
|
||||
* Engine::Model whether it is active and forward the input if it is the case.
|
||||
* Otherwise we just execute the binding for the key (if it exists).
|
||||
*
|
||||
* \code
|
||||
* Controller::OnKeyDown (SDLKey key) {
|
||||
* if (mConsole->GetActive ())
|
||||
* mConsole->OnKeyDown (key);
|
||||
*
|
||||
* if (mBinding[key].size())
|
||||
* mCommands->QueueCommand (mBinding[key]);
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \section addcommand Adding a Command to the Command System
|
||||
*
|
||||
* For the various Modules such as Engine::Controller, Engine::View, etc.
|
||||
* separate files exist in which commands are defined. The filename pattern is
|
||||
* usually [ModuleName]Commands.cc and contains the function
|
||||
* \code void ModuleName::OnRegisterCommands () \endcode which is run during the
|
||||
* initialization phase of the Engine in Engine::OnInit.
|
||||
*
|
||||
* Commands themselves have the signature:
|
||||
* \code bool Cmd_CrazyCommand (std::vector<std::string> args) \endcode
|
||||
* and return true on success and error if some error has happened. The
|
||||
* prefix \e Cmd_ is not mandatory but keeps things clear.
|
||||
*
|
||||
* Please make sure to call Engine::CommandSetErrorString in such a case. The
|
||||
* message itself will be automatically reported to the Engine::Logging system
|
||||
* as a warning since Command errors are hopefully not that important that
|
||||
* they can crash the whole Engine.
|
||||
*
|
||||
* To register a Command to the Engine::Commands system you have to call \code
|
||||
* AddCommand ("crazycommand", Cmd_CrazyCommand); \endcode in
|
||||
* ModuleName::OnRegisterCommands. With this the Command is accessible through
|
||||
* the Command system.
|
||||
*
|
||||
* \section addvariable Adding a Variable to the Engine::Variable System
|
||||
*
|
||||
* To register a variable to the Engine::Variables Module one \e must use a
|
||||
* static variable of type Engine::Variable and use a special constructor:
|
||||
* \code
|
||||
* static Var_Variable PlayerSpeed ("playerspeed", "1.25");
|
||||
* \endcode
|
||||
* This constructor takes care of registering the Variable PlayerSpeedVariable
|
||||
* and its value to the Engine::Variables Module. The first argument is the
|
||||
* name of the variable which can be used to retrieve a pointer to the
|
||||
* Variable with Engine::GetVariable, Engine::GetVariableString, etc. The
|
||||
* second argument is the value which the system will automatically try to
|
||||
* convert to a float. This float is then returned if Engine::GetVariableFloat
|
||||
* is called.
|
||||
*
|
||||
* The prefix \e Var_ is for readability in the code.
|
||||
*
|
||||
* The keyword \e static ensures that the lifespan of the variable is not only
|
||||
* in a local function environment and thus mandatory. However it is
|
||||
* registered at that time the program executes the first time the line in
|
||||
* which the definition was made. To be safe define all your variables in the
|
||||
* global scope of te source file of your Engine::Module.
|
||||
*/
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef _GLOBALS_H
|
||||
#define _GLOBALS_H
|
||||
|
||||
#define LOG_DEFAULT_LEVEL LogLevelMessage
|
||||
#define LOG_MAX_MESSAGE_LENGTH 1024
|
||||
|
||||
#define VIEW_DEFAULT_HEIGHT 600
|
||||
#define VIEW_DEFAULT_WIDTH 800
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#endif // _GLOBALS_H
|
||||
@@ -0,0 +1,166 @@
|
||||
#ifndef KEYTABLE_H
|
||||
#define KEYTABLE_H
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
/** \brief Defines the key codes for mouse buttons
|
||||
*
|
||||
* With this enum we can treat mouse button events the same way as we treat
|
||||
* keyboard events. To do so we define the left button as the last keyboard
|
||||
* button.
|
||||
*/
|
||||
enum MouseButton {
|
||||
MouseButtonUnknown = SDLK_LAST,
|
||||
MouseButtonLeft,
|
||||
MouseButtonMiddle,
|
||||
MouseButtonRight,
|
||||
MouseButtonWheelUp,
|
||||
MouseButtonWheelDown,
|
||||
MouseButtonLast
|
||||
};
|
||||
|
||||
struct key_definition {
|
||||
int keynum;
|
||||
const char *keystr;
|
||||
};
|
||||
|
||||
const int keytable_last = MouseButtonLast;
|
||||
|
||||
static const key_definition key_table[] = {
|
||||
{SDLK_BACKSPACE, "backspace"},
|
||||
{SDLK_TAB, "tab"},
|
||||
// {SDLK_CLEAR, "12"},
|
||||
{SDLK_RETURN, "return"},
|
||||
{SDLK_PAUSE, "pause"},
|
||||
{SDLK_ESCAPE, "escape"},
|
||||
{SDLK_SPACE, "space"},
|
||||
{SDLK_EXCLAIM, "exclaim"},
|
||||
// {SDLK_QUOTEDBL, ""},
|
||||
{SDLK_HASH, "#"},
|
||||
{SDLK_DOLLAR, "$"},
|
||||
{SDLK_AMPERSAND, "&"},
|
||||
// {SDLK_QUOTE, "39"},
|
||||
// {SDLK_LEFTPAREN, "("},
|
||||
// {SDLK_RIGHTPAREN, ")"},
|
||||
// {SDLK_ASTERISK, "*"},
|
||||
{SDLK_PLUS, "+"},
|
||||
{SDLK_COMMA, ","},
|
||||
{SDLK_MINUS, "-"},
|
||||
{SDLK_PERIOD, "."},
|
||||
{SDLK_SLASH, "/"},
|
||||
{SDLK_0, "0"},
|
||||
{SDLK_1, "1"},
|
||||
{SDLK_2, "2"},
|
||||
{SDLK_3, "3"},
|
||||
{SDLK_4, "4"},
|
||||
{SDLK_5, "5"},
|
||||
{SDLK_6, "6"},
|
||||
{SDLK_7, "7"},
|
||||
{SDLK_8, "8"},
|
||||
{SDLK_9, "9"},
|
||||
{SDLK_COLON, ":"},
|
||||
{SDLK_SEMICOLON, ";"},
|
||||
{SDLK_LESS, "<"},
|
||||
{SDLK_EQUALS, "="},
|
||||
{SDLK_GREATER, ">"},
|
||||
{SDLK_QUESTION, "?"},
|
||||
{SDLK_AT, "@"},
|
||||
{SDLK_LEFTBRACKET, "["},
|
||||
{SDLK_BACKSLASH, "\\"},
|
||||
{SDLK_RIGHTBRACKET, "]"},
|
||||
{SDLK_CARET, "^"},
|
||||
{SDLK_UNDERSCORE, "_"},
|
||||
{SDLK_BACKQUOTE, "`"},
|
||||
{SDLK_a, "a"},
|
||||
{SDLK_b, "b"},
|
||||
{SDLK_c, "c"},
|
||||
{SDLK_d, "d"},
|
||||
{SDLK_e, "e"},
|
||||
{SDLK_f, "f"},
|
||||
{SDLK_g, "g"},
|
||||
{SDLK_h, "h"},
|
||||
{SDLK_i, "i"},
|
||||
{SDLK_j, "j"},
|
||||
{SDLK_k, "k"},
|
||||
{SDLK_l, "l"},
|
||||
{SDLK_m, "m"},
|
||||
{SDLK_n, "n"},
|
||||
{SDLK_o, "o"},
|
||||
{SDLK_p, "p"},
|
||||
{SDLK_q, "q"},
|
||||
{SDLK_r, "r"},
|
||||
{SDLK_s, "s"},
|
||||
{SDLK_t, "t"},
|
||||
{SDLK_u, "u"},
|
||||
{SDLK_v, "v"},
|
||||
{SDLK_w, "w"},
|
||||
{SDLK_x, "x"},
|
||||
{SDLK_y, "y"},
|
||||
{SDLK_z, "z"},
|
||||
{SDLK_KP0, "keypad_0"},
|
||||
{SDLK_KP1, "keypad_1"},
|
||||
{SDLK_KP2, "keypad_2"},
|
||||
{SDLK_KP3, "keypad_3"},
|
||||
{SDLK_KP4, "keypad_4"},
|
||||
{SDLK_KP5, "keypad_5"},
|
||||
{SDLK_KP6, "keypad_6"},
|
||||
{SDLK_KP7, "keypad_7"},
|
||||
{SDLK_KP8, "keypad_8"},
|
||||
{SDLK_KP9, "keypad_9"},
|
||||
{SDLK_KP_PERIOD, "keypad_period"},
|
||||
{SDLK_KP_DIVIDE, "keypad_devide"},
|
||||
{SDLK_KP_MULTIPLY, "keypad_multiply"},
|
||||
{SDLK_KP_MINUS, "keypad_minus"},
|
||||
{SDLK_KP_PLUS, "keypad_plus"},
|
||||
{SDLK_KP_ENTER, "keypad_enter"},
|
||||
{SDLK_KP_EQUALS, "keypad_equals"},
|
||||
{SDLK_UP, "up"},
|
||||
{SDLK_DOWN, "down"},
|
||||
{SDLK_RIGHT, "right"},
|
||||
{SDLK_LEFT, "left"},
|
||||
{SDLK_INSERT, "insert"},
|
||||
{SDLK_HOME, "home"},
|
||||
{SDLK_END, "end"},
|
||||
{SDLK_PAGEUP, "pageup"},
|
||||
{SDLK_PAGEDOWN, "pagedown"},
|
||||
{SDLK_F1, "f1"},
|
||||
{SDLK_F2, "f2"},
|
||||
{SDLK_F3, "f3"},
|
||||
{SDLK_F4, "f4"},
|
||||
{SDLK_F5, "f5"},
|
||||
{SDLK_F6, "f6"},
|
||||
{SDLK_F7, "f7"},
|
||||
{SDLK_F8, "f8"},
|
||||
{SDLK_F9, "f9"},
|
||||
{SDLK_F10, "f10"},
|
||||
{SDLK_F11, "f11"},
|
||||
{SDLK_F12, "f12"},
|
||||
{SDLK_F13, "f13"},
|
||||
{SDLK_F14, "f14"},
|
||||
{SDLK_F15, "f15"},
|
||||
{SDLK_NUMLOCK, "numlock"},
|
||||
{SDLK_CAPSLOCK, "capslock"},
|
||||
{SDLK_SCROLLOCK, "scrollock"},
|
||||
{SDLK_RSHIFT, "right_shift"},
|
||||
{SDLK_LSHIFT, "left_shift"},
|
||||
{SDLK_RCTRL, "right_ctrl"},
|
||||
{SDLK_LCTRL, "left_ctrl"},
|
||||
{SDLK_RALT, "right_alt"},
|
||||
{SDLK_LALT, "left_alt"},
|
||||
{SDLK_RMETA, "right_meta"},
|
||||
{SDLK_LMETA, "left_meta"},
|
||||
{SDLK_LSUPER, "left_super"}, /* Left "Windows" key */
|
||||
{SDLK_RSUPER, "right_super"}, /* Right "Windows" key */
|
||||
{SDLK_MODE, "altgr"}, /* "Alt Gr" key */
|
||||
{SDLK_COMPOSE, "compose"}, /* Multi-key compose key */
|
||||
{SDLK_DELETE, "delete"},
|
||||
{MouseButtonLeft, "mouse_left"},
|
||||
{MouseButtonMiddle, "mouse_middle"},
|
||||
{MouseButtonRight, "mouse_right"},
|
||||
{MouseButtonWheelUp, "mouse_wheelup"},
|
||||
{MouseButtonWheelDown, "mouse_wheeldown"},
|
||||
{keytable_last, NULL}
|
||||
};
|
||||
|
||||
#endif /* KEYTABLE_H */
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
ADD_SUBDIRECTORY ( mathlib )
|
||||
ADD_SUBDIRECTORY ( coll2d )
|
||||
ADD_SUBDIRECTORY ( oglft )
|
||||
@@ -0,0 +1,28 @@
|
||||
# - Try to find UnitTest++
|
||||
#
|
||||
#
|
||||
|
||||
SET (UNITTEST++_FOUND FALSE)
|
||||
|
||||
FIND_PATH (UNITTEST++_INCLUDE_DIR UnitTest++.h /usr/include/unittest++ /usr/local/include/unittest++ $ENV{UNITTESTXX_PATH}/src $ENV{UNITTESTXX_INCLUDE_PATH})
|
||||
|
||||
FIND_LIBRARY (UNITTEST++_LIBRARY NAMES UnitTest++ PATHS /usr/lib /usr/local/lib $ENV{UNITTESTXX_PATH} ENV{UNITTESTXX_LIBRARY_PATH})
|
||||
|
||||
IF (UNITTEST++_INCLUDE_DIR AND UNITTEST++_LIBRARY)
|
||||
SET (UNITTEST++_FOUND TRUE)
|
||||
ENDIF (UNITTEST++_INCLUDE_DIR AND UNITTEST++_LIBRARY)
|
||||
|
||||
IF (UNITTEST++_FOUND)
|
||||
IF (NOT UnitTest++_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found UnitTest++: ${UNITTEST++_LIBRARY}")
|
||||
ENDIF (NOT UnitTest++_FIND_QUIETLY)
|
||||
ELSE (UNITTEST++_FOUND)
|
||||
IF (UnitTest++_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find UnitTest++")
|
||||
ENDIF (UnitTest++_FIND_REQUIRED)
|
||||
ENDIF (UNITTEST++_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED (
|
||||
UNITTEST++_INCLUDE_DIR
|
||||
UNITTEST++_LIBRARY
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
PROJECT (COLL2D)
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED (VERSION 2.6)
|
||||
|
||||
# Needed for UnitTest++
|
||||
LIST( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake )
|
||||
|
||||
SET ( COLL2D_SRCS
|
||||
src/coll2d.cc
|
||||
)
|
||||
|
||||
INCLUDE_DIRECTORIES ( include ../mathlib/ )
|
||||
|
||||
SET_TARGET_PROPERTIES ( ${PROJECT_EXECUTABLES} PROPERTIES
|
||||
LINKER_LANGUAGE CXX
|
||||
)
|
||||
|
||||
SUBDIRS (tests)
|
||||
|
||||
ADD_LIBRARY ( coll2d ${COLL2D_SRCS} )
|
||||
|
||||
@@ -0,0 +1,346 @@
|
||||
#ifndef _COLL2D_H
|
||||
#define _COLL2D_H
|
||||
|
||||
/** \brief Coll2d - A 2d collision detection library
|
||||
* \author Martin Felis <martin@silef.de>
|
||||
*
|
||||
* This library provides functions to detect collisions between polygons and
|
||||
* spheres.
|
||||
*
|
||||
* Notes:
|
||||
* - vertices of polygons are described in local coordinates
|
||||
* - return values of check_collision are in global coordinates
|
||||
* - all Shapes get copied to a temporary instance which will then get
|
||||
* transferred into global coordinates
|
||||
* - Polygons are assumed to be convex and the vertices are stored
|
||||
* counter clockwise.
|
||||
* - The transformation of the global position and velocities towards
|
||||
* relative position and velocities happens in the
|
||||
* int check_collision_<type>_<type> functions!
|
||||
*/
|
||||
|
||||
#include <mathlib.h>
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
|
||||
#include <coll2d_errors.h>
|
||||
|
||||
namespace coll2d {
|
||||
|
||||
/** \brief Contains the information of a collision
|
||||
*
|
||||
* \param normal The normal of the reference plane
|
||||
* \param point The actual point where the collision happens in global
|
||||
* cooldinates
|
||||
* \param time If both objects move for this amount of time the contact
|
||||
* will occur.
|
||||
* \param reference_shape
|
||||
* If 0, the first shape passed to he check_collision function
|
||||
* is the reference shape, otherwise the second.
|
||||
*/
|
||||
struct CollisionInfo {
|
||||
vector3d normal;
|
||||
vector3d point;
|
||||
float time;
|
||||
int reference_shape;
|
||||
|
||||
CollisionInfo () : normal (0., 0., 0.), point (0., 0., 0.), time (-1.), reference_shape (-1) {
|
||||
}
|
||||
|
||||
CollisionInfo& operator= (const CollisionInfo& info) {
|
||||
if (this != &info) {
|
||||
normal = info.normal;
|
||||
point = info.point;
|
||||
time = info.time;
|
||||
reference_shape = info.reference_shape;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void doPrint (const char* msg) {
|
||||
std::cout << msg;
|
||||
std::cout << "Time = " << time << std::endl;
|
||||
normal.print ("Normal = ");
|
||||
point.print ( "Point = ");
|
||||
std::cout << "Reference = " << reference_shape << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
/** \brief Base class for all shapes
|
||||
*
|
||||
*/
|
||||
class Shape {
|
||||
protected:
|
||||
vector3d mPosition;
|
||||
vector3d mVelocity;
|
||||
float mAngle;
|
||||
float mAngleVelocity;
|
||||
|
||||
virtual void dummy() {
|
||||
}
|
||||
public:
|
||||
Shape():
|
||||
mPosition (0., 0., 0.),
|
||||
mVelocity (0., 0., 0.),
|
||||
mAngle (0.),
|
||||
mAngleVelocity (0.) {
|
||||
}
|
||||
Shape (const Shape &shape):
|
||||
mPosition (shape.mPosition),
|
||||
mVelocity (shape.mVelocity),
|
||||
mAngle (shape.mAngle),
|
||||
mAngleVelocity (shape.mAngleVelocity)
|
||||
{ }
|
||||
|
||||
virtual ~Shape () {};
|
||||
|
||||
/** \brief Creates and returns a copy of itself */
|
||||
virtual Shape* getCopy () = 0;
|
||||
|
||||
void setPosition(vector3d position) {
|
||||
mPosition = position;
|
||||
}
|
||||
vector3d getPosition() {
|
||||
return mPosition;
|
||||
}
|
||||
void setVelocity(vector3d velocity) {
|
||||
mVelocity = velocity;
|
||||
}
|
||||
vector3d getVelocity() {
|
||||
return mVelocity;
|
||||
}
|
||||
|
||||
void setAngle (const float &angle) {
|
||||
mAngle = angle;
|
||||
}
|
||||
float getAngle () {
|
||||
return mAngle;
|
||||
}
|
||||
void setAngleVelocity (float angle_velocity) {
|
||||
mAngleVelocity = angle_velocity;
|
||||
}
|
||||
float getAngleVelocity () {
|
||||
return mAngleVelocity;
|
||||
}
|
||||
|
||||
virtual void doPrintType() {
|
||||
std::cout << "Shape" << std::endl;
|
||||
}
|
||||
virtual void doPrint (const char* name) {
|
||||
std::cout << name << "<unknown shape>" << std::endl;
|
||||
}
|
||||
friend int check_collision_rel(Shape *shape_a, Shape *shape_b,
|
||||
vector3d *velocity_b, CollisionInfo* info);
|
||||
};
|
||||
|
||||
class Polygon: public Shape {
|
||||
private:
|
||||
unsigned int mVerticeCount;
|
||||
vector3d *mVertices;
|
||||
bool mFreeVertices;
|
||||
public:
|
||||
Polygon() {
|
||||
mVerticeCount = 0;
|
||||
mVertices = NULL;
|
||||
mFreeVertices = false;
|
||||
}
|
||||
Polygon(unsigned int n) {
|
||||
mVerticeCount = n;
|
||||
mVertices = new vector3d[n];
|
||||
mFreeVertices = true;
|
||||
}
|
||||
Polygon(unsigned int n, vector3d *vertices) {
|
||||
mVerticeCount = n;
|
||||
mFreeVertices = false;
|
||||
|
||||
if (vertices == NULL && n > 0) {
|
||||
mVertices = new vector3d [n];
|
||||
mFreeVertices = true;
|
||||
}
|
||||
|
||||
mVertices = vertices;
|
||||
}
|
||||
Polygon (const Polygon &polygon) : Shape (polygon) {
|
||||
mVerticeCount = polygon.mVerticeCount;
|
||||
mFreeVertices = true;
|
||||
|
||||
mVertices = new vector3d[mVerticeCount];
|
||||
memcpy (mVertices, polygon.mVertices, sizeof (vector3d) * mVerticeCount);
|
||||
}
|
||||
virtual ~Polygon () {
|
||||
if (mFreeVertices == true && mVertices)
|
||||
delete[] mVertices;
|
||||
}
|
||||
|
||||
virtual Polygon* getCopy () {
|
||||
Polygon *copy = new Polygon (*this);
|
||||
|
||||
assert (copy);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
virtual void doPrintType() {
|
||||
std::cout << "Polygon" << std::endl;
|
||||
}
|
||||
|
||||
virtual void doPrint (const char* name) {
|
||||
std::cout << name << " (Polygon)" << std::endl;
|
||||
|
||||
std::cout << "mVerticeCount = " << mVerticeCount << std::endl;
|
||||
unsigned int i;
|
||||
for (i = 0; i < mVerticeCount; i ++) {
|
||||
std::cout << i << " = " << mVertices[i][0] << ", " <<
|
||||
mVertices[i][1] << ", " <<
|
||||
mVertices[i][2] << std::endl;
|
||||
}
|
||||
std::cout << "mPosition = " << mPosition[0] <<", " <<
|
||||
mPosition[1] << ", " <<
|
||||
mPosition[2] << std::endl;
|
||||
|
||||
std::cout << "mVelocity = " << mVelocity[0] <<", " <<
|
||||
mVelocity[1] << ", " <<
|
||||
mVelocity[2] << std::endl;
|
||||
|
||||
std::cout << "mAngle = " << mAngle << std::endl;
|
||||
std::cout << "mAngleVelocity = " << mAngleVelocity << std::endl;
|
||||
}
|
||||
|
||||
unsigned int getVerticeCount () {
|
||||
return mVerticeCount;
|
||||
}
|
||||
|
||||
vector3d& getVertice (unsigned int i) {
|
||||
assert (i >= 0 && i < mVerticeCount);
|
||||
return mVertices [i];
|
||||
}
|
||||
|
||||
void setVertice (unsigned int i, const vector3d &vertice) {
|
||||
assert (i >= 0 && i < mVerticeCount);
|
||||
mVertices[i] = vertice;
|
||||
}
|
||||
|
||||
friend int check_collision_polygon_sphere(Shape *polygon_a,
|
||||
Shape *sphere_b, CollisionInfo* info);
|
||||
};
|
||||
|
||||
class Sphere: public Shape {
|
||||
private:
|
||||
float mRadius;
|
||||
public:
|
||||
Sphere (float radius) {
|
||||
mRadius = radius;
|
||||
Shape::setPosition (vector3d (0., 0., 0.));
|
||||
}
|
||||
|
||||
Sphere(float radius, const vector3d &position) {
|
||||
mRadius = radius;
|
||||
Shape::setPosition(position);
|
||||
}
|
||||
|
||||
Sphere (const Sphere &sphere):
|
||||
Shape (sphere),
|
||||
mRadius (sphere.mRadius) { }
|
||||
|
||||
virtual Sphere* getCopy() {
|
||||
Sphere* copy = new Sphere (*this);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
virtual void doPrintType() {
|
||||
std::cout << "Sphere" << std::endl;
|
||||
}
|
||||
|
||||
virtual void doPrint (const char* name) {
|
||||
std::cout << name << " (Sphere)" << std::endl;
|
||||
|
||||
std::cout << "mRadius = " << mRadius << std::endl;
|
||||
std::cout << "mPosition = " << mPosition[0] <<", " <<
|
||||
mPosition[1] << ", " <<
|
||||
mPosition[2] << std::endl;
|
||||
|
||||
std::cout << "mVelocity = " << mVelocity[0] <<", " <<
|
||||
mVelocity[1] << ", " <<
|
||||
mVelocity[2] << std::endl;
|
||||
|
||||
std::cout << "mAngle = " << mAngle << std::endl;
|
||||
std::cout << "mAngleVelocity = " << mAngleVelocity << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void setRadius (float radius) {
|
||||
mRadius = radius;
|
||||
}
|
||||
|
||||
float getRadius () {
|
||||
return mRadius;
|
||||
}
|
||||
|
||||
friend int check_collision_polygon_sphere(Shape *polygon_a,
|
||||
Shape *sphere_b, CollisionInfo* info);
|
||||
};
|
||||
|
||||
/** \brief The higher level function to call for collision detection
|
||||
*
|
||||
* \param stepsize the timestep within we want to check for the collision
|
||||
* \param shape_a first shape
|
||||
* \param shape_b second shape
|
||||
* \param info information about the collision will be to info
|
||||
*
|
||||
* \returns 0 - no collision, negative on error, positive on collision
|
||||
*/
|
||||
int check_collision(float timestep, Shape *shape_a, Shape *shape_b, CollisionInfo* info);
|
||||
|
||||
/** \brief The higher level function to call for collision detection
|
||||
*
|
||||
* \param shape_a first shape
|
||||
* \param shape_b second shape
|
||||
* \param velocity_b relative velocity of b to a
|
||||
* \param info information about the collision will be to info
|
||||
*
|
||||
* \returns 0 - no collision, negative on error, positive on collision
|
||||
*/
|
||||
int check_collision_rel(float timestep, Shape *shape_a, Shape *shape_b, vector3d *velocity_b,
|
||||
CollisionInfo* info);
|
||||
|
||||
/** \brief Callback signature for the check functions */
|
||||
typedef int (*check_cb)(float timestep, Shape *shape_a, Shape *shape_b, CollisionInfo* info);
|
||||
|
||||
/** \brief Returns the check functions which performs the checks depending
|
||||
* on their types. */
|
||||
check_cb get_check(Shape *shape_a, Shape *shape_b);
|
||||
|
||||
/** \brief Performs a check between a polygon and a sphere
|
||||
*/
|
||||
int check_collision_polygon_sphere(float timestep, Shape *shape_a, Shape *shape_b,
|
||||
CollisionInfo* info);
|
||||
|
||||
/** \brief Performs a check between a sphere and a sphere
|
||||
*/
|
||||
int check_collision_sphere_sphere(float timestep, Shape *shape_a, Shape *shape_b,
|
||||
CollisionInfo* info);
|
||||
|
||||
|
||||
/** \brief Calculates the time it takes for a point to touch a plane
|
||||
*
|
||||
* \param normal normal vector of the plane
|
||||
* \param plane_point point on the vector
|
||||
* \param point point that is moving
|
||||
* \param velocity velocity of the point
|
||||
*
|
||||
* \returns -1 if point is moving away from the plane (or is below and
|
||||
* moves even further below
|
||||
* >= 0 if point is moving along the plane or towards the plane
|
||||
*
|
||||
* This function depends on the scale of velocity. It is assumed
|
||||
* that velocity represents the displacement in one frame. In this
|
||||
* case a return value > 1 means there will not be a contact
|
||||
* within this frame.
|
||||
*/
|
||||
float calculate_contact_plane_point(vector3d &normal, vector3d &plane_point, vector3d &point, vector3d &velocity);
|
||||
|
||||
}
|
||||
|
||||
#endif /* _COLL2D_H */
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef _COLL2D_ERRORS
|
||||
#define _COLL2D_ERRORS
|
||||
|
||||
#define CHECK_ERROR_UNKNOWN -9999
|
||||
#define CHECK_ERROR_NOT_IMPLEMENTED -1
|
||||
#define CHECK_ERROR_INVALID_TYPES -2
|
||||
#define CHECK_ERROR_OVERLAP -3
|
||||
|
||||
#endif /* _COLL2D_ERRORS */
|
||||
@@ -0,0 +1,572 @@
|
||||
#include <cstring>
|
||||
#include<coll2d.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace coll2d {
|
||||
|
||||
int check_collision (float timestep, Shape *shape_a, Shape *shape_b, CollisionInfo *info) {
|
||||
check_cb check = NULL;
|
||||
|
||||
check = get_check (shape_a, shape_b);
|
||||
|
||||
if ( check == NULL ) {
|
||||
return CHECK_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return check (timestep, shape_a, shape_b, info);
|
||||
};
|
||||
|
||||
check_cb get_check (Shape *shape_a, Shape *shape_b) {
|
||||
if ( (dynamic_cast<Polygon*> (shape_a) != NULL)
|
||||
&& (dynamic_cast<Sphere*> (shape_b) != NULL) ) {
|
||||
return check_collision_polygon_sphere;
|
||||
}
|
||||
else if ( (dynamic_cast<Polygon*> (shape_b) != NULL)
|
||||
&& (dynamic_cast<Sphere*> (shape_a) != NULL) ) {
|
||||
return check_collision_polygon_sphere;
|
||||
} else if ( (dynamic_cast<Sphere*> (shape_b) != NULL)
|
||||
&& (dynamic_cast<Sphere*> (shape_a) != NULL) ) {
|
||||
return check_collision_sphere_sphere;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int check_collision_rel (float timestep, Shape *shape_a, Shape *shape_b, vector3d *velocity_b, CollisionInfo *info) {
|
||||
check_cb check = NULL;
|
||||
|
||||
shape_b->setVelocity (*velocity_b);
|
||||
check = get_check (shape_a, shape_b);
|
||||
|
||||
if ( check == NULL ) {
|
||||
return CHECK_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return check (timestep, shape_a, shape_b, info);
|
||||
};
|
||||
|
||||
/** \brief calculates the time for a moving point to touch a plane
|
||||
*
|
||||
* \param normal The normal of the plane
|
||||
* \param plane_point a point on the plane
|
||||
* \param point the moving point
|
||||
* \param velocity the velocity of the point
|
||||
*
|
||||
* \returns If the return value is negative, the point is moving away from the
|
||||
* plane or is below the plane and thus does not touch it. Otherwise
|
||||
* point + (return value) * velocity
|
||||
* is on the plane.
|
||||
*/
|
||||
float calculate_contact_plane_point (vector3d &normal, vector3d &plane_point, vector3d &point, vector3d &velocity) {
|
||||
vector3d temp_vector (point);
|
||||
temp_vector -= plane_point;
|
||||
|
||||
// If the following is < 0 then the point is "below" the plane
|
||||
if (normal * temp_vector < 0) {
|
||||
// If the following is < 0 then we move even deeper
|
||||
if ( normal * velocity < 0 )
|
||||
return -999;
|
||||
// Or towards the upper side of the plane.
|
||||
else
|
||||
return -111;
|
||||
}
|
||||
|
||||
int i,imax = -1;
|
||||
float vmax = 0.;
|
||||
for (i = 0; i < 3; i++) {
|
||||
if ( normal[i] * velocity[i] < vmax) {
|
||||
vmax = normal[i] * velocity[i];
|
||||
imax = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (imax == -1) {
|
||||
return -1.;
|
||||
}
|
||||
|
||||
return (normal[imax] * plane_point[imax] - normal[imax] * point[imax]) / vmax;
|
||||
}
|
||||
|
||||
// #define VERBOSE_PHASE
|
||||
|
||||
/** \brief Checks whether a sphere penetrates one of the polygones edges
|
||||
*
|
||||
* This check only finds intersections of the sphere with one of the sides in
|
||||
* other words it will not find intersections with the vertices. As for convex
|
||||
* polygons a sphere will either touch one of the edges or one of the
|
||||
* vertices.
|
||||
*
|
||||
* First thing we do is calculate the normals pointing out of the polygon.
|
||||
* Then for each edge e of the polygon (is being done by the function
|
||||
* calculate_contatc_plane_point (...):
|
||||
* - Calculate the point that would be the first to touch edge e if a contact
|
||||
* occurs
|
||||
* - Calculate the time it would take for this point to touch the edge with
|
||||
* the relative velocity of the sphere
|
||||
*
|
||||
* Next we calculatefor each edge the point on the sphere which would be the first to touch
|
||||
* the polygon, if it was moving towards the current edge.
|
||||
*/
|
||||
int check_collision_polygon_sphere_sides (Shape *shape_a, Shape *shape_b, CollisionInfo *info) {
|
||||
Polygon* polygon = dynamic_cast<Polygon*> (shape_a);
|
||||
Sphere* sphere = dynamic_cast<Sphere*> (shape_b);
|
||||
|
||||
if ( polygon == NULL && sphere == NULL) {
|
||||
polygon = dynamic_cast<Polygon*> (shape_b);
|
||||
sphere = dynamic_cast<Sphere*> (shape_a);
|
||||
}
|
||||
|
||||
if (!polygon || !sphere) {
|
||||
return CHECK_ERROR_INVALID_TYPES;
|
||||
}
|
||||
|
||||
vector3d velocity_sphere = sphere->getVelocity();
|
||||
|
||||
vector3d temp_vector (velocity_sphere);
|
||||
if (temp_vector.length2() == 0.)
|
||||
return 0;
|
||||
|
||||
// Calculate the normals pointing OUT of the polygon
|
||||
float *t = NULL, t_min = 10000.;
|
||||
unsigned int i,j,vertices,count = 0;
|
||||
vertices = polygon->getVerticeCount();
|
||||
vector3d *normals = NULL;
|
||||
vector3d side (0., 0., 0.);
|
||||
vector3d up (0., 1., 0.);
|
||||
/*
|
||||
if (polygon->getPosition().length() > 0.) {
|
||||
for (i = 0; i < vertices; i++) {
|
||||
polygon->getVertice(i) += polygon->getPosition();
|
||||
}
|
||||
}
|
||||
*/
|
||||
// normals contains all the normal vectors out of
|
||||
// the polygon
|
||||
normals = new vector3d[vertices];
|
||||
// The array t contains the time it takes until the sphere
|
||||
// would touch the plane with the given velocity
|
||||
t = new float[vertices];
|
||||
|
||||
for (i = 0; i < vertices; i++) {
|
||||
j = (i + 1) % vertices;
|
||||
side = polygon->getVertice(j);
|
||||
side -= polygon->getVertice(i);
|
||||
normals[i] = cross_product (side, up);
|
||||
normals[i] /= normals[i].length ();
|
||||
|
||||
// temp_vector is the point on the sphere that would touch the plane first
|
||||
// if it was directly moving towards it
|
||||
temp_vector = normals[i];
|
||||
temp_vector *= - sphere->getRadius();
|
||||
temp_vector += sphere->getPosition();
|
||||
|
||||
t[i] = calculate_contact_plane_point (normals[i], polygon->getVertice(i), temp_vector, velocity_sphere);
|
||||
|
||||
#ifdef VERBOSE_PHASE
|
||||
cout << "= next =" << endl;
|
||||
cout << "t[" << i << "] = " << t[i] << " normal = "; normals[i].print ();
|
||||
cout << "point = "; temp_vector.print();
|
||||
cout << "plane point = "; polygon->getVertice(i).print();
|
||||
#endif
|
||||
if (t[i] < 0)
|
||||
normals[i].setValues (0., 0., 0.);
|
||||
else {
|
||||
if (t[i] < t_min)
|
||||
t_min = t[i];
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
delete[] t;
|
||||
delete[] normals;
|
||||
return 0;
|
||||
}
|
||||
|
||||
vector3d contact_point, cp_near;
|
||||
|
||||
/// \ToDo: Instead of checking all planes, remember which ones to check
|
||||
for (i = 0; i < vertices; i++) {
|
||||
if ( t[i] >= 0) {
|
||||
// So there seems to occur an collision. Now we have to check,
|
||||
// whether this is actually between the points that define the
|
||||
// plane.
|
||||
unsigned int min_distance_vertex_index = i, other_vertice = (i + 1) % vertices;
|
||||
float min_distance;
|
||||
j = (i + 1) % vertices;
|
||||
// First we calculate the actual contact point:
|
||||
temp_vector = normals[i];
|
||||
temp_vector *= - sphere->getRadius();
|
||||
temp_vector *= t[i];
|
||||
temp_vector += sphere->getPosition();
|
||||
|
||||
contact_point = normals[i];
|
||||
contact_point *= -sphere->getRadius();
|
||||
contact_point += temp_vector;
|
||||
|
||||
// Now we calculate to which vertice this point is closer:
|
||||
temp_vector = contact_point;
|
||||
temp_vector -= polygon->getVertice(i);
|
||||
min_distance = temp_vector.length2 ();
|
||||
|
||||
temp_vector = contact_point;
|
||||
temp_vector -= polygon->getVertice(j);
|
||||
|
||||
if (min_distance > temp_vector.length2 ()) {
|
||||
min_distance_vertex_index = j;
|
||||
other_vertice = i;
|
||||
}
|
||||
|
||||
// Then we want to see, whether the contact point actually lies
|
||||
// on the vector that goes from one vertice to the other. For
|
||||
// this we calculate (cp - near) * (far - near). The value
|
||||
// cannot be greater than 1. (otherwise we would have picked
|
||||
// the other vector as near. If it is < 0 then it is outside
|
||||
// of the polygon.
|
||||
temp_vector = polygon->getVertice(other_vertice);
|
||||
temp_vector -= polygon->getVertice(min_distance_vertex_index);
|
||||
|
||||
temp_vector /= temp_vector.length();
|
||||
|
||||
cp_near = contact_point;
|
||||
cp_near -= polygon->getVertice(min_distance_vertex_index);
|
||||
|
||||
float val = cp_near * temp_vector;
|
||||
if ( (val >= 0 && val <= 1) && (t[i] <= 1.)) {
|
||||
info->time = t[i];
|
||||
info->normal = normals[i];
|
||||
|
||||
info->point = sphere->getPosition();
|
||||
info->point += sphere->getVelocity() * t[i];
|
||||
info->point -= normals[i] * sphere->getRadius ();
|
||||
|
||||
delete[] t;
|
||||
delete[] normals;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if ( (t_min <= 1.) && (t_min >= 0.)) {
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
||||
delete[] t;
|
||||
delete[] normals;
|
||||
|
||||
if (t_min > 1.)
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
// return CHECK_ERROR_UNKNOWN;
|
||||
};
|
||||
|
||||
int check_collision_polygon_sphere_vertices (Shape *shape_a, Shape *shape_b, CollisionInfo *info) {
|
||||
Polygon* polygon = dynamic_cast<Polygon*> (shape_a);
|
||||
Sphere* sphere = dynamic_cast<Sphere*> (shape_b);
|
||||
|
||||
if ( polygon == NULL && sphere == NULL) {
|
||||
polygon = dynamic_cast<Polygon*> (shape_b);
|
||||
sphere = dynamic_cast<Sphere*> (shape_a);
|
||||
}
|
||||
|
||||
if (!polygon || !sphere) {
|
||||
return CHECK_ERROR_INVALID_TYPES;
|
||||
}
|
||||
|
||||
// Transform global velocities to relative velocities:
|
||||
/*
|
||||
sphere->setVelocity (sphere->getVelocity() - polygon->getVelocity());
|
||||
*/
|
||||
vector3d velocity_sphere = sphere->getVelocity();
|
||||
|
||||
vector3d temp_vector (velocity_sphere);
|
||||
if (temp_vector.length2() == 0.) {
|
||||
#ifdef VERBOSE_PHASE
|
||||
cout << "sphere has no velocity!" << endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
vector3d contact_point, cp_near;
|
||||
|
||||
// Okay if we happen to be here, there still might be one of
|
||||
// the corners colliding with the sphere.
|
||||
float a, b, c, t1, t2, t_min = 10000;
|
||||
unsigned int i, j, vertices;
|
||||
vector3d position (sphere->getPosition());
|
||||
vector3d velocity (sphere->getVelocity());
|
||||
float radius = sphere->getRadius();
|
||||
vertices = polygon->getVerticeCount();
|
||||
|
||||
for (i = 0; i < vertices; i++) {
|
||||
vector3d vertice (polygon->getVertice(i));
|
||||
a = b = c = 0;
|
||||
|
||||
// We must ensure that all happens in the x-z-plane (so y == 0.)
|
||||
vertice[1] = 0.;
|
||||
position[1] = 0.;
|
||||
|
||||
vector3d distance_sphere_vertice;
|
||||
for (j = 0; j < 3; j++) {
|
||||
distance_sphere_vertice[j] = position[j] - vertice[j];
|
||||
}
|
||||
#ifdef VERBOSE_PHASE
|
||||
cout << " ===== " << endl;
|
||||
cout << "vertice = ";
|
||||
vertice.print ();
|
||||
velocity.print ();
|
||||
position.print ();
|
||||
cout << "radius = " << radius << endl;
|
||||
cout << "distance = " << distance_sphere_vertice.length () << endl;;
|
||||
#endif
|
||||
for (j = 0; j < 3; j++) {
|
||||
a += velocity[j]*velocity[j];
|
||||
b += 2 * velocity[j] * (position[j] - vertice[j]);
|
||||
c += position[j] * position[j] - 2 * position[j] * vertice[j] + vertice[j] * vertice[j];
|
||||
}
|
||||
c -= radius * radius;
|
||||
|
||||
if (solve_quadratic (a, b, c, &t1, &t2)) {
|
||||
// cout << "solve_quadratic = " << t1 << "\t" << t2 << endl;
|
||||
float t_temp_min = t2;
|
||||
if (t1 < t2)
|
||||
t_temp_min = t1;
|
||||
|
||||
if (t_temp_min < t_min) {
|
||||
if ((t_temp_min <= 1.) && (t_temp_min >= 0.)) {
|
||||
t_min = t_temp_min;
|
||||
temp_vector = position;
|
||||
temp_vector -= vertice;
|
||||
temp_vector /= temp_vector.length ();
|
||||
#ifdef VERBOSE_PHASE
|
||||
cout << "new closest point t = " << t_min << endl;
|
||||
#endif
|
||||
info->time = t_min;
|
||||
info->normal = temp_vector;
|
||||
info->point = vertice;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( (t_min <= 1.) && (t_min >= 0.)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (t_min > 1.)
|
||||
return 0;
|
||||
|
||||
return CHECK_ERROR_UNKNOWN;
|
||||
};
|
||||
|
||||
int check_collision_polygon_sphere (float timestep, Shape *shape_a, Shape *shape_b, CollisionInfo *info) {
|
||||
/* If the first shape given is a sphere and the second one a shape, we have
|
||||
* to remember it to set the right value to *info.
|
||||
*/
|
||||
bool swapped = false;
|
||||
Polygon* polygon_cast_test = dynamic_cast<Polygon*> (shape_a);
|
||||
Sphere* sphere_cast_test = dynamic_cast<Sphere*> (shape_b);
|
||||
|
||||
if ( polygon_cast_test == NULL && sphere_cast_test == NULL) {
|
||||
polygon_cast_test = dynamic_cast<Polygon*> (shape_b);
|
||||
sphere_cast_test = dynamic_cast<Sphere*> (shape_a);
|
||||
|
||||
swapped = true;
|
||||
}
|
||||
|
||||
if (!polygon_cast_test || !sphere_cast_test) {
|
||||
return CHECK_ERROR_INVALID_TYPES;
|
||||
}
|
||||
|
||||
Polygon polygon_copy (*polygon_cast_test);
|
||||
Sphere sphere_copy (*sphere_cast_test);
|
||||
|
||||
unsigned int vertices;
|
||||
vertices = polygon_copy.getVerticeCount();
|
||||
|
||||
#ifdef VERBOSE_PHASE
|
||||
cout << "======== New Polygon Sphere Test: Phase 1" << endl;
|
||||
if (swapped)
|
||||
cout << "Swapped!" << endl;
|
||||
cout << "Polygon position: ";
|
||||
polygon_copy.getPosition().print ();
|
||||
cout << "Polygon velocity: ";
|
||||
polygon_copy.getVelocity().print ();
|
||||
cout << "Sphere position: ";
|
||||
sphere_copy.getPosition().print ();
|
||||
cout << "Sphere velocity: ";
|
||||
sphere_copy.getVelocity().print ();
|
||||
cout << "Timestep : " << timestep << endl;
|
||||
|
||||
cout << "Vertices before transformation = " << endl;
|
||||
int i;
|
||||
for (i = 0; i < vertices; i++) {
|
||||
polygon_copy.getVertice(i).print();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Here we translate the polygon and its velocity into the reference frame
|
||||
// of the polygon.
|
||||
sphere_copy.setPosition (sphere_copy.getPosition() - polygon_copy.getPosition());
|
||||
sphere_copy.setPosition (sphere_copy.getPosition().rotate_y (-polygon_copy.getAngle()));
|
||||
// Here scale the velocity so that our time horizon lies in [0., 1.]
|
||||
sphere_copy.setVelocity ((sphere_copy.getVelocity() - polygon_copy.getVelocity() ) * timestep );
|
||||
sphere_copy.setVelocity (sphere_copy.getVelocity().rotate_y (-polygon_copy.getAngle()));
|
||||
|
||||
#ifdef VERBOSE_PHASE
|
||||
cout << "Vertices after transformation = " << endl;
|
||||
for (i = 0; i < vertices; i++) {
|
||||
polygon_copy.getVertice(i).print();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VERBOSE_PHASE
|
||||
cout << "After transformation:" << endl;
|
||||
cout << "Polygon position: ";
|
||||
polygon_copy.getPosition().print ();
|
||||
cout << "Polygon velocity: ";
|
||||
polygon_copy.getVelocity().print ();
|
||||
cout << "Sphere position: ";
|
||||
sphere_copy.getPosition().print ();
|
||||
cout << "Sphere velocity: ";
|
||||
sphere_copy.getVelocity().print ();
|
||||
#endif
|
||||
|
||||
CollisionInfo sides_info;
|
||||
CollisionInfo vertices_info;
|
||||
int sides_result = 0, vertices_result = 0;
|
||||
|
||||
/* Tricky part: Since polygons are assumed to be convex and we calculated
|
||||
* with both methods a collision, we take the sides result. Since they are
|
||||
* convex the first event to happen is the collision with the side.
|
||||
* Otherwise it would first touch the vertice and then the side, which is
|
||||
* not possible. (\Todo true?)
|
||||
*/
|
||||
|
||||
sides_result = check_collision_polygon_sphere_sides (&polygon_copy, &sphere_copy, &sides_info);
|
||||
// We have to transform the time back to [0., timestep]
|
||||
sides_info.time *= timestep;
|
||||
#ifdef VERBOSE_PHASE
|
||||
cout << "sides_result = " << sides_result << " t = " << sides_info.time << endl;
|
||||
#endif
|
||||
if (sides_result > 0) {
|
||||
sides_info.point.rotate_y (polygon_copy.getAngle());
|
||||
sides_info.normal.rotate_y (polygon_copy.getAngle());
|
||||
sides_info.point += polygon_copy.getPosition();
|
||||
memcpy (info, &sides_info, sizeof (CollisionInfo));
|
||||
sides_info.time *= timestep;
|
||||
if (swapped == true) {
|
||||
info->reference_shape = 1;
|
||||
} else {
|
||||
info->reference_shape = 0;
|
||||
}
|
||||
return sides_result;
|
||||
}
|
||||
|
||||
vertices_result = check_collision_polygon_sphere_vertices (&polygon_copy, &sphere_copy, &vertices_info);
|
||||
// We have to transform the time back to [0., timestep]
|
||||
vertices_info.time *= timestep;
|
||||
#ifdef VERBOSE_PHASE
|
||||
cout << "vertices_res = " << vertices_result << " t = " << vertices_info.time << endl;
|
||||
cout << "vertices_point = ";
|
||||
vertices_info.point.print();
|
||||
#endif
|
||||
if (vertices_result > 0) {
|
||||
vertices_info.point.rotate_y (polygon_copy.getAngle());
|
||||
vertices_info.normal.rotate_y (polygon_copy.getAngle());
|
||||
vertices_info.point += polygon_copy.getPosition();
|
||||
memcpy (info, &vertices_info, sizeof (CollisionInfo));
|
||||
if (swapped == true) {
|
||||
info->reference_shape = 1;
|
||||
} else {
|
||||
info->reference_shape = 0;
|
||||
}
|
||||
return vertices_result;
|
||||
}
|
||||
|
||||
if ((sides_result == 0) && (vertices_result == 0))
|
||||
return 0;
|
||||
|
||||
return CHECK_ERROR_UNKNOWN;
|
||||
};
|
||||
|
||||
int check_collision_sphere_sphere (float timestep, Shape *shape_a, Shape *shape_b, CollisionInfo *info) {
|
||||
/* If the first shape given is a sphere and the second one a shape, we have
|
||||
* to remember it to set the right value to *info.
|
||||
*/
|
||||
Sphere* sphere_test_a = dynamic_cast<Sphere*> (shape_a);
|
||||
Sphere* sphere_test_b = dynamic_cast<Sphere*> (shape_b);
|
||||
|
||||
if (!sphere_test_a || !sphere_test_b) {
|
||||
return CHECK_ERROR_INVALID_TYPES;
|
||||
}
|
||||
|
||||
Sphere sphere_a (*sphere_test_a);
|
||||
Sphere sphere_b (*sphere_test_b);
|
||||
|
||||
// First we check whether there is actually a relative velocity towards each
|
||||
// other:
|
||||
vector3d rel_velocity = sphere_b.getVelocity ();
|
||||
rel_velocity -= sphere_a.getVelocity ();
|
||||
rel_velocity *= timestep;
|
||||
if (rel_velocity.length2() == 0.)
|
||||
return 0;
|
||||
|
||||
vector3d rel_position = sphere_b.getPosition ();
|
||||
rel_position -= sphere_a.getPosition ();
|
||||
|
||||
// We need to ignore height differences
|
||||
rel_position[1] = 0.;
|
||||
rel_velocity[1] = 0.;
|
||||
|
||||
vector3d rel_position_norm = rel_position;
|
||||
rel_position_norm.normalize ();
|
||||
|
||||
float velocity_projection = rel_position_norm * rel_velocity;
|
||||
float distance = rel_position.length();
|
||||
|
||||
if (velocity_projection >= 0.)
|
||||
return 0;
|
||||
|
||||
float t = (- distance + sphere_a.getRadius () + sphere_b.getRadius ()) / velocity_projection;
|
||||
|
||||
#ifdef VERBOSE_PHASE
|
||||
cout << "==== New Sphere Sphere Test ====" << endl;
|
||||
cout << "Relative Position = ";
|
||||
rel_position.print ();
|
||||
cout << "Relative Velocity = ";
|
||||
rel_velocity.print ();
|
||||
cout << "velocity_projection = " << velocity_projection << endl;
|
||||
cout << "distance = " << distance << endl;
|
||||
cout << "- distance + Ra + Rb = " << - distance + sphere_a.getRadius () + sphere_b.getRadius () << endl;
|
||||
cout << "t = " << t << endl;
|
||||
#endif
|
||||
|
||||
// if t < 0 this means we would have to move back in time
|
||||
// to get to the point where the two spheres touched. In other words: they
|
||||
// are overlapping, hence it is an invalid state!
|
||||
if (t < 0)
|
||||
return CHECK_ERROR_OVERLAP;
|
||||
if (t > 1)
|
||||
return 0;
|
||||
|
||||
info->point = sphere_a.getPosition() + rel_position_norm * t;
|
||||
info->time = t * timestep;
|
||||
|
||||
if (sphere_a.getVelocity().length2() == 0.) {
|
||||
info->normal = rel_position_norm;
|
||||
info->reference_shape = 0;
|
||||
} else {
|
||||
info->normal = rel_position_norm * -1.;
|
||||
info->reference_shape = 1;
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
PROJECT (ENGINETESTS)
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED (VERSION 2.6)
|
||||
|
||||
# Needed for UnitTest++
|
||||
LIST( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../CMake )
|
||||
|
||||
SET ( TESTS_SRCS
|
||||
main.cc
|
||||
general.cc
|
||||
polygon_sphere.cc
|
||||
sphere_sphere.cc
|
||||
)
|
||||
|
||||
FIND_PACKAGE (UnitTest++)
|
||||
|
||||
INCLUDE_DIRECTORIES ( ../mathlib/ )
|
||||
|
||||
SET_TARGET_PROPERTIES ( ${PROJECT_EXECUTABLES} PROPERTIES
|
||||
LINKER_LANGUAGE CXX
|
||||
)
|
||||
|
||||
IF ( UNITTEST++_FOUND )
|
||||
|
||||
ADD_EXECUTABLE ( coll2dtests ${TESTS_SRCS} )
|
||||
|
||||
INCLUDE_DIRECTORIES ( ${UNITTEST++_INCLUDE_DIR} )
|
||||
|
||||
SET_TARGET_PROPERTIES ( coll2dtests PROPERTIES
|
||||
LINKER_LANGUAGE CXX
|
||||
OUTPUT_NAME runtests
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES ( coll2dtests
|
||||
${UNITTEST++_LIBRARY}
|
||||
mathlib
|
||||
coll2d
|
||||
)
|
||||
|
||||
OPTION (RUN_AUTOMATIC_TESTS "Perform automatic tests after compilation?" OFF)
|
||||
|
||||
IF (RUN_AUTOMATIC_TESTS)
|
||||
ADD_CUSTOM_COMMAND (TARGET coll2dtests
|
||||
POST_BUILD
|
||||
COMMAND coll2dtests
|
||||
COMMENT "Running automated tests..."
|
||||
)
|
||||
ENDIF (RUN_AUTOMATIC_TESTS)
|
||||
|
||||
ENDIF ( UNITTEST++_FOUND )
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
#include <UnitTest++.h>
|
||||
|
||||
#include <coll2d.h>
|
||||
|
||||
using namespace coll2d;
|
||||
using namespace std;
|
||||
|
||||
TEST ( SphereCopyConstructer ) {
|
||||
Sphere sphere_a (123.);
|
||||
sphere_a.setVelocity (vector3d(1., 2., 3.));
|
||||
|
||||
Sphere sphere_b (sphere_a);
|
||||
CHECK_EQUAL (sphere_a.getRadius (), sphere_b.getRadius ());
|
||||
|
||||
vector3d velocity_a = sphere_a.getVelocity ();
|
||||
vector3d velocity_b = sphere_b.getVelocity ();
|
||||
|
||||
CHECK (velocity_a == velocity_b );
|
||||
|
||||
sphere_b.setVelocity (vector3d (0., 0., 0.));
|
||||
|
||||
velocity_a = sphere_a.getVelocity ();
|
||||
velocity_b = sphere_b.getVelocity ();
|
||||
|
||||
CHECK (velocity_a != velocity_b );
|
||||
}
|
||||
|
||||
TEST ( PolygonCopyConstructer ) {
|
||||
Polygon polygon_a (3);
|
||||
|
||||
vector3d vertice0 (-1., 0., -1.);
|
||||
vector3d vertice1 (1., 0., -1.);
|
||||
vector3d vertice2 (0., 0., 1.);
|
||||
|
||||
polygon_a.setVertice (0, vertice0);
|
||||
polygon_a.setVertice (1, vertice1);
|
||||
polygon_a.setVertice (2, vertice2);
|
||||
|
||||
polygon_a.setVelocity (vector3d(1., 2., 3.));
|
||||
|
||||
Polygon polygon_b (polygon_a);
|
||||
|
||||
vector3d velocity_a = polygon_a.getVelocity ();
|
||||
vector3d velocity_b = polygon_b.getVelocity ();
|
||||
|
||||
CHECK (vertice0 == polygon_b.getVertice (0));
|
||||
CHECK (vertice1 == polygon_b.getVertice (1));
|
||||
CHECK (vertice2 == polygon_b.getVertice (2));
|
||||
|
||||
polygon_b.setVelocity (vector3d (0., 0., 0.));
|
||||
velocity_a = polygon_a.getVelocity ();
|
||||
velocity_b = polygon_b.getVelocity ();
|
||||
|
||||
CHECK (velocity_a != velocity_b );
|
||||
}
|
||||
|
||||
/** Checks whether we identify the different shapes
|
||||
* correctly.
|
||||
*/
|
||||
TEST ( CheckShapeType ) {
|
||||
vector3d sphere_position (0., 0., 0.);
|
||||
|
||||
Shape* polygon = new Polygon (0, NULL);
|
||||
Shape* sphere = new Sphere (0, sphere_position);
|
||||
|
||||
Shape* cast_test = NULL;
|
||||
|
||||
cast_test = dynamic_cast <Sphere*> ( sphere );
|
||||
CHECK_EQUAL (cast_test, sphere);
|
||||
cast_test = dynamic_cast <Sphere*> ( polygon );
|
||||
CHECK (cast_test == NULL );
|
||||
cast_test = dynamic_cast <Polygon*> (polygon);
|
||||
CHECK_EQUAL (cast_test, polygon);
|
||||
cast_test = dynamic_cast <Polygon*> (sphere);
|
||||
CHECK (cast_test == NULL );
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
/** Checks whether the right check function is chosen
|
||||
*/
|
||||
TEST ( CheckGetCheck ) {
|
||||
vector3d sphere_position (0., 0., 0.);
|
||||
|
||||
Shape* polygon = new Polygon (0, NULL);
|
||||
Shape* sphere = new Sphere (0, sphere_position);
|
||||
|
||||
check_cb check = NULL;
|
||||
|
||||
// polygon - sphere -> polygon_sphere
|
||||
check = get_check (polygon, sphere);
|
||||
CHECK (static_cast<check_cb> (check) == static_cast<check_cb> (check_collision_polygon_sphere));
|
||||
|
||||
// sphere - polygon -> polygon_sphere
|
||||
check = get_check (sphere, polygon);
|
||||
CHECK (static_cast<check_cb> (check) == static_cast<check_cb> (check_collision_polygon_sphere));
|
||||
|
||||
// and we do not want that the pointers have changed!
|
||||
// (as it used to be in previous versions)
|
||||
CHECK (dynamic_cast <Polygon*> (sphere) == NULL);
|
||||
CHECK (dynamic_cast <Sphere*> (polygon) == NULL);
|
||||
|
||||
check = get_check (sphere, sphere);
|
||||
CHECK (check == check_collision_sphere_sphere);
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckErrorNotImplemented ) {
|
||||
Shape* polygon = new Polygon (0, NULL);
|
||||
vector3d velocity (0., 0., 0.);
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_rel (1., polygon, polygon, &velocity, &info);
|
||||
|
||||
CHECK (result == CHECK_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
delete polygon;
|
||||
}
|
||||
|
||||
TEST ( CheckCalculateContactPlanePoint ) {
|
||||
vector3d normal (1., 0., 0.);
|
||||
vector3d plane_point (0., 0., 0.);
|
||||
vector3d point (1., 0., 0.);
|
||||
vector3d velocity (-1., 0., 0);
|
||||
|
||||
float result;
|
||||
|
||||
// Directly moving towards the plane
|
||||
result = calculate_contact_plane_point (normal, plane_point, point, velocity);
|
||||
CHECK_EQUAL (1, result);
|
||||
|
||||
// Moving with a slight angle onto the plane
|
||||
velocity.setValues (-1., 0., 0.2);
|
||||
result = calculate_contact_plane_point (normal, plane_point, point, velocity);
|
||||
CHECK_EQUAL (1, result);
|
||||
|
||||
velocity.setValues (-1., 0., 0.);
|
||||
|
||||
// Point is "below" the plane and moves even deeper
|
||||
plane_point.setValues (2., 0., 0);
|
||||
result = calculate_contact_plane_point (normal, plane_point, point, velocity);
|
||||
CHECK_EQUAL (-999, result);
|
||||
|
||||
// Point is "below" but moves towards the plane
|
||||
velocity.setValues (1., 0., 0);
|
||||
result = calculate_contact_plane_point (normal, plane_point, point, velocity);
|
||||
CHECK_EQUAL (-111, result);
|
||||
}
|
||||
|
||||
TEST ( CheckCollisionStepsize ) {
|
||||
vector3d normal (1., 0., 0.);
|
||||
vector3d plane_point (0., 0., 0.);
|
||||
vector3d point (1., 0., 0.);
|
||||
vector3d velocity (-1., 0., 0);
|
||||
|
||||
float result;
|
||||
|
||||
// Directly moving towards the plane
|
||||
result = calculate_contact_plane_point (normal, plane_point, point, velocity);
|
||||
CHECK_EQUAL (1, result);
|
||||
|
||||
// Moving with a slight angle onto the plane
|
||||
velocity.setValues (-1., 0., 0.2);
|
||||
result = calculate_contact_plane_point (normal, plane_point, point, velocity);
|
||||
CHECK_EQUAL (1, result);
|
||||
|
||||
velocity.setValues (-1., 0., 0.);
|
||||
|
||||
// Point is "below" the plane and moves even deeper
|
||||
plane_point.setValues (2., 0., 0);
|
||||
result = calculate_contact_plane_point (normal, plane_point, point, velocity);
|
||||
CHECK_EQUAL (-999, result);
|
||||
|
||||
// Point is "below" but moves towards the plane
|
||||
velocity.setValues (1., 0., 0);
|
||||
result = calculate_contact_plane_point (normal, plane_point, point, velocity);
|
||||
CHECK_EQUAL (-111, result);
|
||||
}
|
||||
|
||||
/* Here we test, whether the value of info.reference_shape is correct.
|
||||
* If we swap the shapes passed to check_collision, then the value must swap,
|
||||
* too.
|
||||
*/
|
||||
TEST ( CheckReferenceShapeValue ) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
|
||||
// first part of the test, the collision occurs
|
||||
// on an edge
|
||||
vector3d sphere_position (2.3, 0., 0.);
|
||||
Shape* sphere = new Sphere (1, sphere_position);
|
||||
sphere->setVelocity (vector3d (-1., 0., 0.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision (1., polygon, sphere, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK_EQUAL (0, info.reference_shape);
|
||||
|
||||
result = check_collision (1., sphere, polygon, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK_EQUAL (1, info.reference_shape);
|
||||
|
||||
// here the collision occurs on a vertice
|
||||
sphere->setPosition (vector3d (1.5, 0., -2.5));
|
||||
sphere->setVelocity (vector3d (0., 0., 1.));
|
||||
|
||||
result = check_collision (1., sphere, polygon, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK_EQUAL (1, info.reference_shape);
|
||||
|
||||
result = check_collision (1., polygon, sphere, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK_EQUAL (0, info.reference_shape);
|
||||
|
||||
delete sphere;
|
||||
delete polygon;
|
||||
}
|
||||
|
||||
/* Test whether Polygon::getCopy() does what it should */
|
||||
TEST ( CheckPolygonGetCopy ) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Polygon* polygon = new Polygon (4, vertices);
|
||||
Polygon* polygon_copy = polygon->getCopy();
|
||||
|
||||
CHECK (polygon != polygon_copy);
|
||||
CHECK_EQUAL (polygon->getVerticeCount(), polygon_copy->getVerticeCount());
|
||||
|
||||
unsigned int i, count;
|
||||
count = polygon->getVerticeCount ();
|
||||
|
||||
for (i = 0; i < count; i ++) {
|
||||
vector3d vertice = polygon->getVertice (i);
|
||||
vector3d vertice_copy = polygon_copy->getVertice (i);
|
||||
|
||||
int j;
|
||||
for (j = 0; j < 3; j++) {
|
||||
CHECK_EQUAL (vertice[j], vertice_copy[j]);
|
||||
}
|
||||
}
|
||||
|
||||
delete polygon;
|
||||
delete polygon_copy;
|
||||
}
|
||||
|
||||
/* Test whether Sphere::getCopy() does what it should */
|
||||
TEST ( CheckSphereGetCopy ) {
|
||||
Sphere* sphere = new Sphere (1.23);
|
||||
Sphere* sphere_copy = sphere->getCopy();
|
||||
|
||||
CHECK_EQUAL (sphere->getRadius(), sphere_copy->getRadius());
|
||||
CHECK (sphere != sphere_copy);
|
||||
|
||||
delete sphere;
|
||||
delete sphere_copy;
|
||||
}
|
||||
|
||||
TEST ( SphereSetGetRadius ) {
|
||||
Sphere sphere (123.);
|
||||
CHECK_EQUAL (123, sphere.getRadius());
|
||||
|
||||
sphere.setRadius (456.);
|
||||
CHECK_EQUAL (456, sphere.getRadius());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#include <UnitTest++.h>
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
return UnitTest::RunAllTests ();
|
||||
}
|
||||
@@ -0,0 +1,544 @@
|
||||
#include <UnitTest++.h>
|
||||
|
||||
#include <coll2d.h>
|
||||
|
||||
using namespace coll2d;
|
||||
using namespace std;
|
||||
|
||||
TEST ( CheckErrorInvalidTypes ) {
|
||||
Shape* polygon = new Polygon (0, NULL);
|
||||
vector3d velocity (0., 0., 0.);
|
||||
vector3d sphere_position (2.1, 0., 0.);
|
||||
Shape* sphere = new Sphere (1, sphere_position);
|
||||
sphere->setVelocity (vector3d(0., 0., 0.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_polygon_sphere (1., sphere, sphere, &info);
|
||||
CHECK (result == CHECK_ERROR_INVALID_TYPES);
|
||||
|
||||
result = check_collision_polygon_sphere (1., polygon, polygon, &info);
|
||||
CHECK (result == CHECK_ERROR_INVALID_TYPES);
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckCollisionPolygonSphereNoVelocity ) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., -1.);
|
||||
vertices[1].setValues (1., 0., -1.);
|
||||
vertices[2].setValues (1., 0., 1.);
|
||||
vertices[3].setValues (-1., 0., 1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
|
||||
vector3d sphere_position (2.1, 0., 0.);
|
||||
Shape* sphere = new Sphere (1, sphere_position);
|
||||
|
||||
vector3d velocity (0., 0., 0.);
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_rel (1., polygon, sphere, &velocity, &info);
|
||||
|
||||
CHECK (result >= 0);
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckCollisionPolygonSphereDiverging ) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
|
||||
vector3d sphere_position (2.1, 0., 0.);
|
||||
Shape* sphere = new Sphere (1, sphere_position);
|
||||
|
||||
vector3d velocity (1., 0., 0.);
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_rel (1., polygon, sphere, &velocity, &info);
|
||||
|
||||
CHECK (result >= 0);
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckCollisionPolygonSphereContact ) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
|
||||
vector3d sphere_position (2., 0., 0.);
|
||||
Shape* sphere = new Sphere (1, sphere_position);
|
||||
sphere->setVelocity (vector3d (-1., 0., 0.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision (1., polygon, sphere, &info);
|
||||
|
||||
CHECK (result > 0);
|
||||
CHECK_EQUAL (0.0, info.time);
|
||||
CHECK_EQUAL (1., info.normal[0]);
|
||||
CHECK_EQUAL (0., info.normal[1]);
|
||||
CHECK_EQUAL (0., info.normal[2]);
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckCollisionPolygonSphereColliding ) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
|
||||
vector3d sphere_position (2.5, 0., 0.1);
|
||||
Shape* sphere = new Sphere (1, sphere_position);
|
||||
|
||||
vector3d velocity (-1., 0., 0.);
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_rel (1., polygon, sphere, &velocity, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK_EQUAL (0.5, info.time);
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckCollisionPolygonSphereCollidingTop ) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
|
||||
vector3d sphere_position (0., 0., 2.5);
|
||||
Shape* sphere = new Sphere (1, sphere_position);
|
||||
|
||||
vector3d velocity (0., 0., -1.);
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_rel (1., polygon, sphere, &velocity, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK_EQUAL (0.5, info.time);
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckCollisionPolygonSphereCollidingNonPerpendicular ) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
|
||||
vector3d sphere_position (0., 0., 2.5);
|
||||
Shape* sphere = new Sphere (1, sphere_position);
|
||||
|
||||
vector3d velocity (0.01, 0., -1.);
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_rel (1., polygon, sphere, &velocity, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK_EQUAL (0.5, info.time);
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckCollisionPolygonSphereCollidingCorner) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
|
||||
vector3d sphere_position ( 1.5, 0., 2.5);
|
||||
Shape* sphere = new Sphere (1, sphere_position);
|
||||
|
||||
vector3d velocity (0.0, 0., -1.);
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_rel (1., polygon, sphere, &velocity, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
// In this test we make sure, that the z value of both the polygon and the
|
||||
// sphere get ignored:
|
||||
TEST ( CheckCollisionPolygonSphereCollidingCornerIgnoreHeight) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
|
||||
vector3d sphere_position ( 1.5, 10., 2.5);
|
||||
Shape* sphere = new Sphere (1, sphere_position);
|
||||
sphere->setVelocity (vector3d (0., 0., -1.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision (1., polygon, sphere, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
|
||||
vertices[0].setValues (-1., -10., 1.);
|
||||
vertices[1].setValues (1., -10., 1.);
|
||||
vertices[2].setValues (1., -10., -1.);
|
||||
vertices[3].setValues (-1., -10., -1.);
|
||||
|
||||
sphere->setPosition (vector3d (1.5, 0., 2.5));
|
||||
result = check_collision (1., polygon, sphere, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckCollisionPolygonSphereCollidingCornerTop) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
|
||||
vector3d sphere_position (1.5, 0., - 2.5);
|
||||
Shape* sphere = new Sphere (1, sphere_position);
|
||||
|
||||
vector3d velocity (0., 0., 1.);
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_rel (1., polygon, sphere, &velocity, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckCollisionPolygonSphereCollidingCornerNeighbour) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., -0.99);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
|
||||
vector3d sphere_position (1.5 , 0., - 2.5);
|
||||
Shape* sphere = new Sphere (1, sphere_position);
|
||||
|
||||
vector3d velocity (0., 0., 1.);
|
||||
|
||||
CollisionInfo info;
|
||||
check_collision_rel (1., polygon, sphere, &velocity, &info);
|
||||
|
||||
CHECK (info.point == vertices[2]);
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckCollisionPolygonSphereNonCollidingSetPosition ) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
|
||||
vector3d sphere_position (2.5, 0., 0.1);
|
||||
Shape* sphere = new Sphere (1, sphere_position);
|
||||
sphere->setPosition (vector3d (35, 0, 0));
|
||||
vector3d velocity (-1., 0., 0.);
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_rel (1., polygon, sphere, &velocity, &info);
|
||||
|
||||
CHECK_EQUAL (0, result);
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
// In this test we set the velocity of the polygon instead of the
|
||||
// sphere.
|
||||
TEST ( CheckCollisionPolygonSphereCollidingPolygonSetVelocity ) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
|
||||
vector3d sphere_position (2.5, 0., 0.);
|
||||
Shape* sphere = new Sphere (1, sphere_position);
|
||||
|
||||
vector3d velocity (1., 0., 0.);
|
||||
polygon->setVelocity (velocity);
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision (1., polygon, sphere, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK_EQUAL (0.5, info.time);
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckSetGetAngle ) {
|
||||
Shape* polygon = new Polygon (0, NULL);
|
||||
|
||||
polygon->setAngle (0.1234567);
|
||||
|
||||
CHECK (fabs (0.1234567 - polygon->getAngle ()) < 1.0e-7);
|
||||
|
||||
delete polygon;
|
||||
}
|
||||
|
||||
TEST ( CheckCollisionPolygonSphereDiamond ) {
|
||||
vector3d vertices[4];
|
||||
float sqrt2 = sqrt (2);
|
||||
|
||||
vertices[0].setValues (-sqrt2, 0., 0.);
|
||||
vertices[1].setValues (0., 0., sqrt2);
|
||||
vertices[2].setValues (sqrt2, 0., 0.);
|
||||
vertices[3].setValues (0., 0., -sqrt2);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
|
||||
Shape* sphere = new Sphere (1., vector3d (sqrt2 + 1.5, 0., 0.));
|
||||
sphere->setVelocity (vector3d (-1., 0., 0.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision (1., polygon, sphere, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK (fabs (0.5 - info.time) <= 1.0e-6);
|
||||
CHECK_EQUAL (0, info.reference_shape);
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckPolygonSpherePassingBy ) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
|
||||
vector3d sphere_position (1., 0., 2.5);
|
||||
Shape* sphere = new Sphere (1, sphere_position);
|
||||
sphere->setVelocity (vector3d (-2., 0., 0.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision (1., polygon, sphere, &info);
|
||||
|
||||
CHECK_EQUAL (0, result);
|
||||
|
||||
delete sphere;
|
||||
delete polygon;
|
||||
}
|
||||
|
||||
TEST ( CheckCollisionPolygonSphereReturnValuePoint ) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
polygon->setPosition (vector3d (sqrt (2), 0., - sqrt (2)));
|
||||
polygon->setAngle (M_PI * 0.25);
|
||||
|
||||
Shape* sphere = new Sphere (1, vector3d (-sqrt(2) * 0.5, 0., sqrt (2) * 0.5));
|
||||
sphere->setVelocity (vector3d (sqrt (2), 0., -sqrt(2)));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision (1., polygon, sphere, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK ( fabs (0.5 - info.time) < 1.0e-6);
|
||||
CHECK ( (info.point - vector3d (sqrt (2) * 0.5, 0., -sqrt(2) * 0.5)).length() < 1.0e-6 );
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckCollisionPolygonSphereReturnValuePointTranslated ) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
polygon->setPosition (vector3d (sqrt (2) + 1., 0., - sqrt (2) - 1.));
|
||||
polygon->setAngle (M_PI * 0.25);
|
||||
|
||||
Shape* sphere = new Sphere (1, vector3d (-sqrt(2) * 0.5 + 1., 0., sqrt (2) * 0.5 -1.));
|
||||
sphere->setVelocity (vector3d (sqrt (2), 0., -sqrt(2)));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision (1., polygon, sphere, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK ( fabs (0.5 - info.time) < 1.0e-6);
|
||||
CHECK ( (info.point - vector3d (sqrt (2) * 0.5 + 1, 0., -sqrt(2) * 0.5 - 1.)).length() < 1.0e-6 );
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckCollisionPolygonSphereReturnValuePointVerticeTranslated ) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
polygon->setPosition (vector3d (0. + 2., 0., - sqrt (2) - 1.5));
|
||||
polygon->setAngle (M_PI * 0.25);
|
||||
|
||||
Shape* sphere = new Sphere (1, vector3d (0. + 2., 0., 0.));
|
||||
sphere->setVelocity (vector3d (0. , 0., -1.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision (1., polygon, sphere, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK ( fabs (0.5 - info.time) < 1.0e-6);
|
||||
CHECK ( (info.point - vector3d (0. + 2., 0., -1.5)).length() < 1.0e-6 );
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckCollisionPolygonSphereReferenceShapePolygon ) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
polygon->setPosition (vector3d (0., 0., 0.));
|
||||
polygon->setVelocity (vector3d (1., 0., 0.));
|
||||
|
||||
Shape* sphere = new Sphere (1, vector3d (2.5, 0., 0.));
|
||||
sphere->setVelocity (vector3d (0., 0., 0.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision (1., polygon, sphere, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK ( fabs (0.5 - info.time) < 1.0e-6);
|
||||
CHECK_EQUAL ( 0, info.reference_shape );
|
||||
|
||||
polygon->setPosition (vector3d (0., 0., 0.));
|
||||
polygon->setVelocity (vector3d (1., 0., 0.));
|
||||
sphere->setPosition (vector3d (2.5, 0., 0.));
|
||||
sphere->setVelocity (vector3d (0., 0., 0.));
|
||||
|
||||
result = check_collision (1., sphere, polygon, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK ( fabs (0.5 - info.time) < 1.0e-6);
|
||||
CHECK_EQUAL ( 1, info.reference_shape );
|
||||
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckCollisionPolygonSphereTimestep ) {
|
||||
vector3d vertices[4];
|
||||
|
||||
vertices[0].setValues (-1., 0., 1.);
|
||||
vertices[1].setValues (1., 0., 1.);
|
||||
vertices[2].setValues (1., 0., -1.);
|
||||
vertices[3].setValues (-1., 0., -1.);
|
||||
|
||||
Shape* polygon = new Polygon (4, vertices);
|
||||
|
||||
vector3d sphere_position (2.5, 0., 0.1);
|
||||
Shape* sphere = new Sphere (1, sphere_position);
|
||||
|
||||
vector3d velocity (-1., 0., 0.);
|
||||
sphere->setVelocity (velocity);
|
||||
|
||||
CollisionInfo info;
|
||||
int result;
|
||||
result = check_collision (1., polygon, sphere, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK_EQUAL (0.5, info.time);
|
||||
|
||||
result = check_collision (2., polygon, sphere, &info);
|
||||
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK_EQUAL (0.5, info.time);
|
||||
|
||||
result = check_collision (0.499, polygon, sphere, &info);
|
||||
CHECK_EQUAL (0, result);
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
#include <UnitTest++.h>
|
||||
|
||||
#include <coll2d.h>
|
||||
|
||||
using namespace coll2d;
|
||||
using namespace std;
|
||||
|
||||
TEST ( CheckSphereSphereInvalidTypes ) {
|
||||
Shape* polygon = new Polygon (0, NULL);
|
||||
vector3d velocity (0., 0., 0.);
|
||||
vector3d sphere_position (2.1, 0., 0.);
|
||||
Shape* sphere = new Sphere (1, sphere_position);
|
||||
sphere->setVelocity (vector3d(0., 0., 0.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_sphere_sphere (1., polygon, sphere, &info);
|
||||
CHECK (result == CHECK_ERROR_INVALID_TYPES);
|
||||
|
||||
delete polygon;
|
||||
delete sphere;
|
||||
}
|
||||
|
||||
TEST ( CheckSphereSphereNoVelocity ) {
|
||||
Shape* sphere_a = new Sphere (1., vector3d (0., 0., 0.));
|
||||
Shape* sphere_b = new Sphere (1, vector3d (4., 0., 0.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_sphere_sphere (1., sphere_a, sphere_b, &info);
|
||||
CHECK_EQUAL (0, result);
|
||||
|
||||
delete sphere_a;
|
||||
delete sphere_b;
|
||||
}
|
||||
|
||||
/* This tests whether we report a collision time of 0.0 when two spheres are
|
||||
* in contact with each other
|
||||
*/
|
||||
TEST ( CheckCollisionSphereSphereContact ) {
|
||||
Shape* sphere_a = new Sphere (1., vector3d (0., 0., 0.));
|
||||
Shape* sphere_b = new Sphere (1, vector3d (2., 0., 0.));
|
||||
|
||||
sphere_b->setVelocity (vector3d(-1., 0., 0.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_sphere_sphere (1., sphere_a, sphere_b, &info);
|
||||
|
||||
CHECK (result >= 0);
|
||||
CHECK_EQUAL (0.0, info.time);
|
||||
|
||||
delete sphere_a;
|
||||
delete sphere_b;
|
||||
}
|
||||
|
||||
TEST ( CheckSphereSphereDiverging ) {
|
||||
Shape* sphere_a = new Sphere (1., vector3d (0., 0., 0.));
|
||||
Shape* sphere_b = new Sphere (1, vector3d (4., 0., 0.));
|
||||
|
||||
sphere_b->setVelocity (vector3d (1., 0., 0.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_sphere_sphere (1., sphere_a, sphere_b, &info);
|
||||
CHECK_EQUAL (0, result);
|
||||
|
||||
delete sphere_a;
|
||||
delete sphere_b;
|
||||
}
|
||||
|
||||
TEST ( CheckSphereSphereCollision ) {
|
||||
Shape* sphere_a = new Sphere (1., vector3d (0., 0., 0.));
|
||||
Shape* sphere_b = new Sphere (1, vector3d (3., 0., 0.));
|
||||
|
||||
sphere_b->setVelocity (vector3d (-1., 0., 0.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_sphere_sphere (1., sphere_a, sphere_b, &info);
|
||||
CHECK_EQUAL (1, result);
|
||||
|
||||
delete sphere_a;
|
||||
delete sphere_b;
|
||||
}
|
||||
|
||||
TEST ( CheckSphereSphereCollisionCheckOrder ) {
|
||||
Shape* sphere_a = new Sphere (1., vector3d (0., 0., 0.));
|
||||
Shape* sphere_b = new Sphere (1, vector3d (3., 0., 0.));
|
||||
|
||||
sphere_a->setVelocity (vector3d (1., 0., 0.));
|
||||
sphere_b->setVelocity (vector3d (-1.5, 0., 0.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_sphere_sphere (1., sphere_a, sphere_b, &info);
|
||||
CHECK_EQUAL (1, result);
|
||||
|
||||
vector3d normal = info.normal;
|
||||
result = check_collision_sphere_sphere (1., sphere_b, sphere_a, &info);
|
||||
CHECK_EQUAL (1, result);
|
||||
|
||||
CHECK ( normal[0] == -info.normal[0]);
|
||||
CHECK ( normal[1] == -info.normal[1]);
|
||||
CHECK ( normal[2] == -info.normal[2]);
|
||||
|
||||
delete sphere_a;
|
||||
delete sphere_b;
|
||||
}
|
||||
|
||||
TEST ( CheckSphereSphereNoCollision ) {
|
||||
Shape* sphere_a = new Sphere (1., vector3d (0., 0., 0.));
|
||||
Shape* sphere_b = new Sphere (1, vector3d (3., 0., 0.));
|
||||
|
||||
sphere_b->setVelocity (vector3d (-0.9, 0., 0.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_sphere_sphere (1., sphere_a, sphere_b, &info);
|
||||
CHECK_EQUAL (0, result);
|
||||
|
||||
delete sphere_a;
|
||||
delete sphere_b;
|
||||
}
|
||||
|
||||
TEST ( CheckSphereSphereCollisionResult ) {
|
||||
Shape* sphere_a = new Sphere (1., vector3d (0., 0., 0.));
|
||||
Shape* sphere_b = new Sphere (1, vector3d (2.5, 0., 0.));
|
||||
|
||||
sphere_b->setVelocity (vector3d (-1, 0., 0.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_sphere_sphere (1., sphere_a, sphere_b, &info);
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK_EQUAL (0.5, info.time);
|
||||
|
||||
delete sphere_a;
|
||||
delete sphere_b;
|
||||
}
|
||||
|
||||
TEST ( CheckSphereSphereMovingNonHorizontal ) {
|
||||
Shape* sphere_a = new Sphere (3., vector3d (0., 0., 0.));
|
||||
Shape* sphere_b = new Sphere (1.5, vector3d (3., 0., 4.));
|
||||
|
||||
sphere_a->setVelocity (vector3d (3./5., 0., 4./5.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_sphere_sphere (1., sphere_a, sphere_b, &info);
|
||||
|
||||
vector3d result_normal = vector3d (-3., 0., -4.).normalize();
|
||||
vector3d collision_point = result_normal * -0.5;
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK_EQUAL (0.5, info.time);
|
||||
CHECK_EQUAL (1, info.reference_shape);
|
||||
CHECK (result_normal == info.normal);
|
||||
CHECK (collision_point == info.point);
|
||||
|
||||
sphere_a->setVelocity (vector3d (0., 0., 0.));
|
||||
|
||||
sphere_b->setVelocity (vector3d (-3./5., 0., -4./5.));
|
||||
result = check_collision_sphere_sphere (1., sphere_a, sphere_b, &info);
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK_EQUAL (0.5, info.time);
|
||||
|
||||
delete sphere_a;
|
||||
delete sphere_b;
|
||||
}
|
||||
|
||||
/* If there is one of the sphere non moving we must ensure that we
|
||||
* set the moving one as the incidence shape.
|
||||
*/
|
||||
TEST ( CheckSphereSphereReferenceShape ) {
|
||||
Shape* sphere_a = new Sphere (3., vector3d (0., 0., 0.));
|
||||
Shape* sphere_b = new Sphere (1.5, vector3d (3., 0., 4.));
|
||||
|
||||
sphere_a->setVelocity (vector3d (3./5., 0., 4./5.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_sphere_sphere (1., sphere_a, sphere_b, &info);
|
||||
|
||||
vector3d result_normal = vector3d (-3., 0., -4.).normalize();
|
||||
vector3d collision_point = result_normal * 0.5;
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK_EQUAL (0.5, info.time);
|
||||
CHECK (result_normal == info.normal);
|
||||
CHECK_EQUAL (1, info.reference_shape);
|
||||
|
||||
sphere_a->setVelocity (vector3d (0., 0., 0.));
|
||||
|
||||
sphere_b->setVelocity (vector3d (-3./5., 0., -4./5.));
|
||||
result = check_collision_sphere_sphere (1., sphere_a, sphere_b, &info);
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK (result_normal * -1. == info.normal);
|
||||
CHECK_EQUAL (0.5, info.time);
|
||||
CHECK_EQUAL (0, info.reference_shape);
|
||||
|
||||
delete sphere_a;
|
||||
delete sphere_b;
|
||||
}
|
||||
|
||||
TEST ( CheckSphereSphereIgnoreHeight ) {
|
||||
Shape* sphere_a = new Sphere (1., vector3d (0., 0., 0.));
|
||||
Shape* sphere_b = new Sphere (1, vector3d (3., 0., 0.));
|
||||
|
||||
sphere_b->setVelocity (vector3d (-2., 0., 0.));
|
||||
|
||||
sphere_a->setPosition (vector3d (0., 10., 0.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_sphere_sphere (1., sphere_a, sphere_b, &info);
|
||||
CHECK_EQUAL (1, result);
|
||||
|
||||
delete sphere_a;
|
||||
delete sphere_b;
|
||||
}
|
||||
|
||||
TEST ( CheckSphereSphereCollisionTimestep ) {
|
||||
Shape* sphere_a = new Sphere (1., vector3d (0., 0., 0.));
|
||||
Shape* sphere_b = new Sphere (1, vector3d (3., 0., 0.));
|
||||
|
||||
sphere_b->setVelocity (vector3d (-1., 0., 0.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_sphere_sphere (1., sphere_a, sphere_b, &info);
|
||||
CHECK_EQUAL (1, result);
|
||||
CHECK_EQUAL (1, info.time);
|
||||
|
||||
result = check_collision_sphere_sphere (2., sphere_a, sphere_b, &info);
|
||||
CHECK_EQUAL (1., result);
|
||||
CHECK_EQUAL (1., info.time);
|
||||
|
||||
result = check_collision_sphere_sphere (0.5, sphere_a, sphere_b, &info);
|
||||
CHECK_EQUAL (0, result);
|
||||
|
||||
delete sphere_a;
|
||||
delete sphere_b;
|
||||
}
|
||||
|
||||
TEST ( CheckPerpendicularMovement ) {
|
||||
Shape* sphere_a = new Sphere (0.4, vector3d (0., 0., 0.));
|
||||
Shape* sphere_b = new Sphere (0.4, vector3d (0., 0., -1.));
|
||||
|
||||
sphere_a->setVelocity (vector3d (0., 0., 0.));
|
||||
sphere_b->setVelocity (vector3d (5., 0., 0.));
|
||||
|
||||
CollisionInfo info;
|
||||
int result = check_collision_sphere_sphere (1., sphere_a, sphere_b, &info);
|
||||
CHECK_EQUAL (0, result);
|
||||
|
||||
delete sphere_a;
|
||||
delete sphere_b;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
PROJECT (MATHLIB CXX)
|
||||
|
||||
LIST ( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/ )
|
||||
|
||||
SET ( SRCS
|
||||
mathlib.cc
|
||||
main.cc
|
||||
)
|
||||
|
||||
ADD_LIBRARY ( mathlib mathlib.cc mathlib.h)
|
||||
@@ -0,0 +1,224 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mathlib.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
void sincos (float rad, double *s, double *c){
|
||||
*s = sin (rad);
|
||||
*c = cos (rad);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
vector3d::vector3d ()
|
||||
{
|
||||
values[0] = 0.;
|
||||
values[1] = 0.;
|
||||
values[2] = 0.;
|
||||
}
|
||||
|
||||
vector3d::vector3d (float u, float v, float w)
|
||||
{
|
||||
values[0] = u;
|
||||
values[1] = v;
|
||||
values[2] = w;
|
||||
}
|
||||
|
||||
vector3d::vector3d (const vector3d &vec)
|
||||
{
|
||||
values[0] = vec.values[0];
|
||||
values[1] = vec.values[1];
|
||||
values[2] = vec.values[2];
|
||||
}
|
||||
|
||||
vector3d vector3d::operator=(const vector3d &vec) {
|
||||
if (this != &vec) {
|
||||
values[0] = vec.values[0];
|
||||
values[1] = vec.values[1];
|
||||
values[2] = vec.values[2];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
vector3d::~vector3d ()
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef MATHLIB_INLINE
|
||||
vector3d vector3d::operator* (const float &f)
|
||||
{
|
||||
return vector3d (values[0] * f, values[1] * f, values[2] * f);
|
||||
}
|
||||
|
||||
vector3d vector3d::operator/ (const float &f)
|
||||
{
|
||||
return vector3d (values[0] / f, values[1] / f, values[2] / f);
|
||||
}
|
||||
|
||||
void vector3d::operator*= (const float &f)
|
||||
{
|
||||
values[0] *= f;
|
||||
values[1] *= f;
|
||||
values[2] *= f;
|
||||
}
|
||||
|
||||
void vector3d::operator/= (const float &f)
|
||||
{
|
||||
values[0] /= f;
|
||||
values[1] /= f;
|
||||
values[2] /= f;
|
||||
}
|
||||
|
||||
float vector3d::operator* (const vector3d &vec)
|
||||
{
|
||||
return values[0] * vec.values[0] + values[1] * vec.values[1] + values[2] * vec.values[2];
|
||||
}
|
||||
|
||||
vector3d vector3d::operator+ (const vector3d &vec)
|
||||
{
|
||||
return vector3d (values[0] + vec.values[0], values[1] + vec.values[1], values[2] + vec.values[2]);
|
||||
}
|
||||
|
||||
vector3d vector3d::operator- (const vector3d &vec)
|
||||
{
|
||||
return vector3d (values[0] - vec.values[0], values[1] - vec.values[1], values[2] - vec.values[2]);
|
||||
}
|
||||
|
||||
void vector3d::operator+= (const vector3d &vec)
|
||||
{
|
||||
values[0] += vec.values[0];
|
||||
values[1] += vec.values[1];
|
||||
values[2] += vec.values[2];
|
||||
}
|
||||
|
||||
void vector3d::operator-= (const vector3d &vec)
|
||||
{
|
||||
values[0] -= vec.values[0];
|
||||
values[1] -= vec.values[1];
|
||||
values[2] -= vec.values[2];
|
||||
}
|
||||
|
||||
bool vector3d::operator== (const vector3d &vec)
|
||||
{
|
||||
if ( (values[0]==vec.values[0]) && (values[1]==vec.values[1]) && (values[2]==vec.values[2]) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool vector3d::operator!= (const vector3d &vec)
|
||||
{
|
||||
return ! (operator==(vec));
|
||||
}
|
||||
|
||||
vector3d vector3d::cross (const vector3d &vec)
|
||||
{
|
||||
return vector3d (values[1] * vec.values[2] - values[2] * vec.values[1],
|
||||
values[2] * vec.values[0] - values[0] * vec.values[2],
|
||||
values[0] * vec.values[1] - values[1] * vec.values[0]);
|
||||
}
|
||||
|
||||
float vector3d::length2 ()
|
||||
{
|
||||
return values[0]*values[0] + values[1]*values[1] + values[2]*values[2];
|
||||
}
|
||||
|
||||
float vector3d::length ()
|
||||
{
|
||||
return sqrt (values[0]*values[0] + values[1]*values[1] + values[2]*values[2]);
|
||||
}
|
||||
#endif
|
||||
|
||||
vector3d& vector3d::rotate_x (float angle)
|
||||
{
|
||||
vector3d old (*this);
|
||||
double s,c;
|
||||
sincos (angle, &s, &c);
|
||||
|
||||
values[0] = old[0];
|
||||
values[1] = c * old[1] - s * old[2];
|
||||
values[2] = s * old[1] + c * old[2];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
vector3d& vector3d::rotate_y (float angle)
|
||||
{
|
||||
vector3d old (*this);
|
||||
double s,c;
|
||||
sincos (angle, &s, &c);
|
||||
|
||||
values[0] = c * old[0] + s * old[2];
|
||||
values[1] = old[1];
|
||||
values[2] = - s * old[0] + c * old[2];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
vector3d& vector3d::rotate_z (float angle)
|
||||
{
|
||||
vector3d old (*this);
|
||||
double s,c;
|
||||
sincos (angle, &s, &c);
|
||||
|
||||
values[0] = c * old[0] + -s * old[1];
|
||||
values[1] = s * old[0] + c * old[1];
|
||||
values[2] = old[2];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
vector3d& vector3d::normalize () {
|
||||
float norm = length ();
|
||||
values [0] /= norm;
|
||||
values [1] /= norm;
|
||||
values [2] /= norm;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void vector3d::print ()
|
||||
{
|
||||
std::cout << values[0] << " " << values[1] << " " << values[2] << std::endl;
|
||||
}
|
||||
|
||||
void vector3d::print (const char *str)
|
||||
{
|
||||
std::cout << str << values[0] << " " << values[1] << " " << values[2] << std::endl;
|
||||
}
|
||||
|
||||
vector3d cross_product (vector3d &a, vector3d &b) {
|
||||
return a.cross (b);
|
||||
}
|
||||
|
||||
inline bool point_within (vector3d *a, vector3d *b, vector3d *point);
|
||||
|
||||
vector3d integrate_rk45 (float t, vector3d& ydot, vector3d& y)
|
||||
{
|
||||
vector3d k1 = ydot * t;
|
||||
vector3d k2 = (ydot + k1 / 2) * t;
|
||||
vector3d k3 = (ydot + k2 / 2 ) * t;
|
||||
vector3d k4 = (ydot + k3) * t;
|
||||
|
||||
return y + (k1 + k2 * 2 + k3 * 2 + k4) / 6;
|
||||
}
|
||||
|
||||
vector3d integrate (float t, vector3d& ydot, vector3d& y)
|
||||
{
|
||||
return integrate_rk45 (t, ydot, y);
|
||||
}
|
||||
|
||||
int solve_quadratic (float a, float b, float c, float *x1, float *x2) {
|
||||
if (b*b - 4 * a * c < 0)
|
||||
return 0;
|
||||
*x1 = static_cast<float> ((-b + sqrt (b*b - 4 * a * c)) / (2 * a));
|
||||
*x2 = static_cast<float> ((-b - sqrt (b*b - 4 * a * c)) / (2 * a));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
#ifndef __MATHLIB_H
|
||||
#define __MATHLIB_H
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#define M_PI 3.14159265
|
||||
void sincos (float rad, double *s, double *c);
|
||||
|
||||
#endif
|
||||
|
||||
#define MATHLIB_INLINE
|
||||
|
||||
struct vector3d
|
||||
{
|
||||
float values[3];
|
||||
|
||||
vector3d ();
|
||||
vector3d (float u, float v, float w);
|
||||
vector3d (const vector3d &vec);
|
||||
vector3d operator= (const vector3d &vec);
|
||||
~vector3d ();
|
||||
|
||||
// Setter and getter
|
||||
inline void setValues (float u, float v, float w) {
|
||||
values[0] = u;
|
||||
values[1] = v;
|
||||
values[2] = w;
|
||||
}
|
||||
|
||||
inline float& operator[] (const int index) {
|
||||
assert (index >= 0);
|
||||
assert (index <= 3);
|
||||
|
||||
return values[index];
|
||||
}
|
||||
|
||||
vector3d operator* (const float &f);
|
||||
vector3d operator/ (const float &f);
|
||||
void operator*= (const float &f);
|
||||
void operator/= (const float &f);
|
||||
|
||||
float operator* (const vector3d &vec);
|
||||
vector3d operator+ (const vector3d &vec);
|
||||
vector3d operator- (const vector3d &vec);
|
||||
void operator+= (const vector3d &vec);
|
||||
void operator-= (const vector3d &vec);
|
||||
bool operator== (const vector3d &vec);
|
||||
bool operator!= (const vector3d &vec);
|
||||
vector3d cross (const vector3d &vec);
|
||||
|
||||
float length2 ();
|
||||
float length ();
|
||||
float get_angle () {
|
||||
return atan2 (values[1], values[0]);
|
||||
}
|
||||
|
||||
vector3d &rotate_x (float angle);
|
||||
vector3d &rotate_y (float angle);
|
||||
vector3d &rotate_z (float angle);
|
||||
vector3d &normalize ();
|
||||
|
||||
void print ();
|
||||
void print (const char* str);
|
||||
};
|
||||
|
||||
#ifdef MATHLIB_INLINE
|
||||
|
||||
inline
|
||||
vector3d vector3d::operator* (const float &f)
|
||||
{
|
||||
return vector3d (values[0] * f, values[1] * f, values[2] * f);
|
||||
}
|
||||
|
||||
inline
|
||||
vector3d vector3d::operator/ (const float &f)
|
||||
{
|
||||
return vector3d (values[0] / f, values[1] / f, values[2] / f);
|
||||
}
|
||||
|
||||
inline
|
||||
void vector3d::operator*= (const float &f)
|
||||
{
|
||||
values[0] *= f;
|
||||
values[1] *= f;
|
||||
values[2] *= f;
|
||||
}
|
||||
|
||||
inline
|
||||
void vector3d::operator/= (const float &f)
|
||||
{
|
||||
values[0] /= f;
|
||||
values[1] /= f;
|
||||
values[2] /= f;
|
||||
}
|
||||
|
||||
inline
|
||||
float vector3d::operator* (const vector3d &vec)
|
||||
{
|
||||
return values[0] * vec.values[0] + values[1] * vec.values[1] + values[2] * vec.values[2];
|
||||
}
|
||||
|
||||
inline
|
||||
vector3d vector3d::operator+ (const vector3d &vec)
|
||||
{
|
||||
return vector3d (values[0] + vec.values[0], values[1] + vec.values[1], values[2] + vec.values[2]);
|
||||
}
|
||||
|
||||
inline
|
||||
vector3d vector3d::operator- (const vector3d &vec)
|
||||
{
|
||||
return vector3d (values[0] - vec.values[0], values[1] - vec.values[1], values[2] - vec.values[2]);
|
||||
}
|
||||
|
||||
inline
|
||||
void vector3d::operator+= (const vector3d &vec)
|
||||
{
|
||||
values[0] += vec.values[0];
|
||||
values[1] += vec.values[1];
|
||||
values[2] += vec.values[2];
|
||||
}
|
||||
|
||||
inline
|
||||
void vector3d::operator-= (const vector3d &vec)
|
||||
{
|
||||
values[0] -= vec.values[0];
|
||||
values[1] -= vec.values[1];
|
||||
values[2] -= vec.values[2];
|
||||
}
|
||||
|
||||
inline
|
||||
bool vector3d::operator== (const vector3d &vec)
|
||||
{
|
||||
if ( (values[0]==vec.values[0]) && (values[1]==vec.values[1]) && (values[2]==vec.values[2]) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline
|
||||
bool vector3d::operator!= (const vector3d &vec)
|
||||
{
|
||||
return ! (operator==(vec));
|
||||
}
|
||||
|
||||
inline
|
||||
vector3d vector3d::cross (const vector3d &vec)
|
||||
{
|
||||
return vector3d (values[1] * vec.values[2] - values[2] * vec.values[1],
|
||||
values[2] * vec.values[0] - values[0] * vec.values[2],
|
||||
values[0] * vec.values[1] - values[1] * vec.values[0]);
|
||||
}
|
||||
|
||||
inline
|
||||
float vector3d::length2 ()
|
||||
{
|
||||
return values[0]*values[0] + values[1]*values[1] + values[2]*values[2];
|
||||
}
|
||||
|
||||
inline
|
||||
float vector3d::length ()
|
||||
{
|
||||
return sqrt (values[0]*values[0] + values[1]*values[1] + values[2]*values[2]);
|
||||
}
|
||||
#endif
|
||||
|
||||
vector3d cross_product (vector3d &a, vector3d &b);
|
||||
|
||||
inline bool point_within (vector3d *a, vector3d *b, vector3d *point);
|
||||
|
||||
vector3d integrate_rk45 (float t,vector3d& ydot, vector3d& y);
|
||||
|
||||
vector3d integrate (float t, vector3d& ydot, vector3d& y);
|
||||
|
||||
int solve_quadratic (float a, float b, float c, float *x1, float *x2);
|
||||
|
||||
#endif /* __MATHLIB_H */
|
||||
@@ -0,0 +1,5 @@
|
||||
Authors of OGLFT
|
||||
|
||||
Allen Barnett
|
||||
Oliver Bock
|
||||
Nigel Stewart
|
||||
@@ -0,0 +1,28 @@
|
||||
# Tries to find FREETYPE2 (http://freetype2.bespin.org) a simple and fast
|
||||
# network library by Lee Salzman
|
||||
#
|
||||
|
||||
SET (FREETYPE2_FOUND FALSE)
|
||||
|
||||
FIND_PATH (FREETYPE2_INCLUDE_DIR freetype/freetype.h /usr/include/ /usr/local/include/ /usr/include/freetype2 /usr/local/include/freetype2 $ENV{FREETYPE2_PATH}/include $ENV{FREETYPE2_INCLUDE_PATH})
|
||||
|
||||
FIND_LIBRARY (FREETYPE2_LIBRARIES NAMES freetype PATHS /usr/lib /usr/local/lib $ENV{FREETYPE2_PATH} $ENV{FREETYPE2_PATH}/lib ENV{FREETYPE2_LIBRARY_PATH})
|
||||
|
||||
IF (FREETYPE2_INCLUDE_DIR AND FREETYPE2_LIBRARIES)
|
||||
SET (FREETYPE2_FOUND TRUE)
|
||||
ENDIF (FREETYPE2_INCLUDE_DIR AND FREETYPE2_LIBRARIES)
|
||||
|
||||
IF (FREETYPE2_FOUND)
|
||||
IF (NOT FREETYPE2_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found FREETYPE2: ${FREETYPE2_LIBRARIES}")
|
||||
ENDIF (NOT FREETYPE2_FIND_QUIETLY)
|
||||
ELSE (FREETYPE2_FOUND)
|
||||
IF (FREETYPE2_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find FREETYPE2")
|
||||
ENDIF (FREETYPE2_FIND_REQUIRED)
|
||||
ENDIF (FREETYPE2_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED (
|
||||
FREETYPE2_INCLUDE_DIR
|
||||
FREETYPE2_LIBRARIES
|
||||
)
|
||||
@@ -0,0 +1,63 @@
|
||||
project( OGLFT )
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED (VERSION 2.6)
|
||||
|
||||
Set( CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake )
|
||||
|
||||
FIND_PACKAGE( OpenGL REQUIRED )
|
||||
FIND_PACKAGE( FreeType2 REQUIRED )
|
||||
|
||||
if( ENABLE_QT )
|
||||
find_package( Qt REQUIRED )
|
||||
if( DESIRED_QT_VERSION EQUAL 3 )
|
||||
find_package( KDE3 REQUIRED )
|
||||
endif( DESIRED_QT_VERSION EQUAL 3 )
|
||||
endif( ENABLE_QT )
|
||||
|
||||
if( ENABLE_GLE )
|
||||
find_package( GLE )
|
||||
endif( ENABLE_GLE )
|
||||
|
||||
#
|
||||
# Test to determine if we want the "tripledot" (variable) form of the GLU tesselator callback.
|
||||
#
|
||||
if(NOT GLU_TESS_CALLBACK_TRIPLEDOT)
|
||||
if(WIN32 OR CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
# Skip the compile check for platforms that never need the variable form
|
||||
set(DEFAULT_GLU_TESS_CALLBACK_TRIPLEDOT false)
|
||||
else(WIN32 OR CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
# For other platforms perform the check
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(CheckIncludeFiles)
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENGL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENGL_LIBRARY})
|
||||
check_include_files(OpenGL/gl.h HAVE_OPENGL_DIR)
|
||||
if(HAVE_OPENGL_DIR)
|
||||
set(OPENGL_DIR_PREFIX "OpenGL")
|
||||
else(HAVE_OPENGL_DIR)
|
||||
set(OPENGL_DIR_PREFIX "GL")
|
||||
endif(HAVE_OPENGL_DIR)
|
||||
set(GLUTESS_TEST_SOURCE "
|
||||
#include <${OPENGL_DIR_PREFIX}/gl.h>
|
||||
#include <${OPENGL_DIR_PREFIX}/glu.h>
|
||||
typedef GLvoid (*GLUTessCallback)(...);
|
||||
static void testcb(GLvoid *, void*) { }
|
||||
int main() {
|
||||
GLUtesselator *t = gluNewTess();
|
||||
gluTessCallback(t, GLU_TESS_VERTEX_DATA, GLUTessCallback(testcb));
|
||||
return 0;
|
||||
}
|
||||
")
|
||||
check_cxx_source_compiles("${GLUTESS_TEST_SOURCE}" GLU_Tesselator_Needs_Variable_Parameter_Callback_Convention_Failure_Means_No)
|
||||
set(GLU_TESS_CALLBACK_TRIPLEDOT ${GLU_Tesselator_Needs_Variable_Parameter_Callback_Convention_Failure_Means_No})
|
||||
endif(WIN32 OR CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
endif(NOT GLU_TESS_CALLBACK_TRIPLEDOT)
|
||||
|
||||
add_subdirectory( liboglft )
|
||||
|
||||
set( BUILD_OGLFT_TESTS OFF CACHE BOOL "Build oglft tests." )
|
||||
|
||||
if( BUILD_OGLFT_TESTS )
|
||||
enable_testing()
|
||||
add_subdirectory( tests )
|
||||
endif( BUILD_OGLFT_TESTS )
|
||||
@@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
@@ -0,0 +1,504 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of 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.
|
||||
|
||||
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 GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
@@ -0,0 +1,432 @@
|
||||
2002-07-12 Allen Barnett <allen@lignumcomputing.com>
|
||||
|
||||
* doc/Doxyfile, configure.ac: Updated to version 0.8.
|
||||
|
||||
* liboglft/OGLFT.cpp:
|
||||
Removed unnecessary default arguments from constructors.
|
||||
|
||||
* tests/Makefile.am: Added extra demo3 header.
|
||||
|
||||
* liboglft/OGLFT.h: Improved the Doxygen comments.
|
||||
|
||||
2002-07-11 Allen Barnett <allen@lignumcomputing.com>
|
||||
|
||||
* doc/documentation.dox: Updated to version 0.8 information.
|
||||
|
||||
* NEWS: Added FreeType version warning.
|
||||
|
||||
* liboglft/OGLFT.cpp: Updated to be compilable by G++ 3.
|
||||
|
||||
Minor improvement of Doxygen comments.
|
||||
|
||||
Added height() method. Returns the "line spacing" of the font.
|
||||
|
||||
Added drawing of formatted numbers.
|
||||
|
||||
Made a couple of changes to support newer versions of FreeType:
|
||||
* A default charmap is not activated if there is no UNICODE map.
|
||||
* Adjust creation of monochrome bitmap to account for even
|
||||
number of bytes now in FreeType bitmaps.
|
||||
|
||||
Correctly compute the vector size for each auxiliary face:
|
||||
Type1 and TrueType fonts typically have different EM sizes.
|
||||
|
||||
Reverted to tesselating straight lines with one step.
|
||||
|
||||
* liboglft/OGLFT.h: Updated to be compilable by G++ 3.
|
||||
|
||||
Minor improvement of Doxygen comments.
|
||||
|
||||
Added height() method. Returns the "line spacing" of the font.
|
||||
|
||||
Added drawing of formatted numbers.
|
||||
|
||||
* tests/tutorial3.cpp: Updated to be compilable by G++ 3.
|
||||
|
||||
* tests/tutorial2.cpp: Updated to be compilable by G++ 3.
|
||||
|
||||
Also, minor modification to optionally (at compile time) use a
|
||||
scalable representation. And, made it double buffered since that's the
|
||||
only available visual with the Mach64 driver.
|
||||
|
||||
* tests/tutorial1.cpp, tests/speedtest.cpp, tests/demo.cpp:
|
||||
Updated to be compilable by G++ 3.
|
||||
|
||||
* tests/demo3.cpp: Updated to be compilable by G++ 3.
|
||||
|
||||
Added example of number formatting.
|
||||
|
||||
* tests/demo2.cpp: Updated to be compilable by G++ 3.
|
||||
|
||||
* tests/Demo3UnicodeExample.h: Added GPL header.
|
||||
|
||||
* tests/Demo3UnicodeExample2.h: Initial checkin.
|
||||
|
||||
* README: Improved Qt project instructions.
|
||||
|
||||
* configure.ac: Updated version number.
|
||||
|
||||
* tests/tests.pro, OGLFT.pro, liboglft/liboglft.pro: Initial checkin.
|
||||
|
||||
* README, NEWS: Added new features for version 0.8.
|
||||
|
||||
2002-07-11 Allen Barnett <allen@lignumcomputing.com>
|
||||
|
||||
* doc/documentation.dox: Updated to version 0.8 information.
|
||||
|
||||
* NEWS: Added FreeType version warning.
|
||||
|
||||
* liboglft/OGLFT.cpp: Updated to be compilable by G++ 3.
|
||||
|
||||
Minor improvement of Doxygen comments.
|
||||
|
||||
Added height() method. Returns the "line spacing" of the font.
|
||||
|
||||
Added drawing of formatted numbers.
|
||||
|
||||
Made a couple of changes to support newer versions of FreeType:
|
||||
* A default charmap is not activated if there is no UNICODE map.
|
||||
* Adjust creation of monochrome bitmap to account for even
|
||||
number of bytes now in FreeType bitmaps.
|
||||
|
||||
Correctly compute the vector size for each auxiliary face:
|
||||
Type1 and TrueType fonts typically have different EM sizes.
|
||||
|
||||
Reverted to tesselating straight lines with one step.
|
||||
|
||||
* liboglft/OGLFT.h: Updated to be compilable by G++ 3.
|
||||
|
||||
Minor improvement of Doxygen comments.
|
||||
|
||||
Added height() method. Returns the "line spacing" of the font.
|
||||
|
||||
Added drawing of formatted numbers.
|
||||
|
||||
* tests/tutorial3.cpp: Updated to be compilable by G++ 3.
|
||||
|
||||
* tests/tutorial2.cpp: Updated to be compilable by G++ 3.
|
||||
|
||||
Also, minor modification to optionally (at compile time) use a
|
||||
scalable representation. And, made it double buffered since that's the
|
||||
only available visual with the Mach64 driver.
|
||||
|
||||
* tests/tutorial1.cpp, tests/speedtest.cpp, tests/demo.cpp:
|
||||
Updated to be compilable by G++ 3.
|
||||
|
||||
* tests/demo3.cpp: Updated to be compilable by G++ 3.
|
||||
|
||||
Added example of number formatting.
|
||||
|
||||
* tests/demo2.cpp: Updated to be compilable by G++ 3.
|
||||
|
||||
* tests/Demo3UnicodeExample.h: Added GPL header.
|
||||
|
||||
* tests/Demo3UnicodeExample2.h: Initial checkin.
|
||||
|
||||
* README: Improved Qt project instructions.
|
||||
|
||||
* configure.ac: Updated version number.
|
||||
|
||||
* tests/tests.pro, OGLFT.pro, liboglft/liboglft.pro: Initial checkin.
|
||||
|
||||
* README, NEWS: Added new features for version 0.8.
|
||||
|
||||
2002-03-26 Allen Barnett <allen@lignumcomputing.com>
|
||||
|
||||
* tests/tutorial2.cpp, tests/tutorial1.cpp: Added <config.h>.
|
||||
|
||||
* tests/demo3.cpp:
|
||||
Without GL_RASTER_POSITION_UNCLIPPED_IBM, need to adjust some of the
|
||||
text items so that they are not clipped.
|
||||
|
||||
* tests/demo.cpp:
|
||||
Reduced the size of the font since nVidia's OpenGL version does not
|
||||
support the GL_RASTER_POSITION_UNCLIPPED_IBM.
|
||||
|
||||
* configure.ac:
|
||||
Note that disabling Qt support also removes UNICODE support.
|
||||
|
||||
2002-03-26 allen@llama.lignumcomputing.org <allen@llama>
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/tests/tutorial2.cpp, /home/allen/cvsroot/lignumCAD/OGLFT/tests/tutorial1.cpp:
|
||||
Added <config.h>.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/tests/demo3.cpp:
|
||||
Without GL_RASTER_POSITION_UNCLIPPED_IBM, need to adjust some of the
|
||||
text items so that they are not clipped.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/tests/demo.cpp:
|
||||
Reduced the size of the font since nVidia's OpenGL version does not
|
||||
support the GL_RASTER_POSITION_UNCLIPPED_IBM.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/configure.ac:
|
||||
Note that disabling Qt support also removes UNICODE support.
|
||||
|
||||
2002-03-25 allen@llama.lignumcomputing.org <allen@llama>
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/configure.ac:
|
||||
Update the version number to 0.7.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/tests/Makefile.am:
|
||||
Use the correct name for the embedded font file.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/liboglft/OGLFT.cpp:
|
||||
Updated Doxygen comments.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/tests/demo3.cpp:
|
||||
Use .h for embedded font file to make automake happier.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/tests/demo3.cpp, /home/allen/cvsroot/lignumCAD/OGLFT/tests/Demo3UnicodeExample.c, /home/allen/cvsroot/lignumCAD/OGLFT/tests/Demo3UnicodeExample.sfd, /home/allen/cvsroot/lignumCAD/OGLFT/tests/Demo3UnicodeExample.ttf, /home/allen/cvsroot/lignumCAD/OGLFT/tests/tosrc.pl:
|
||||
Add demo files for UNICODE and multiple fonts.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/doc/documentation.dox:
|
||||
Updated to 0.7.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/liboglft/OGLFT.h:
|
||||
Updated the Doxygen comments.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/NEWS: Addes the latest news.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/README:
|
||||
Mention UNICODE rendering dependence on Qt and how to build the test programs.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/doc/Doxyfile:
|
||||
Updated version number.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/liboglft/OGLFT.h:
|
||||
Fix typos in description of vertical justification enum documentation.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/configure.ac:
|
||||
Now, if you have Qt and don't disable it, the library will compile
|
||||
with UNICODE support, in the form of Qt's QString. Thus, the FLAGS
|
||||
necessary to compile with Qt are propagated through to all the
|
||||
Makefiles.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/liboglft/OGLFT.h:
|
||||
* Added the ability to draw glyphs based on UNICODE characters. Here,
|
||||
we use the Qt UNICODE representation: QString. Additionally, there
|
||||
are methods to set the foreground and background colors using
|
||||
QColor.
|
||||
|
||||
* Made the definition of measure(const char*) explicit in each of
|
||||
Face's immediate subclasses in order to avoid a complaint from
|
||||
gcc 2.95 about "using measure" from Face.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/liboglft/OGLFT.cpp:
|
||||
* Added the ability to draw glyphs based on UNICODE characters. Here,
|
||||
we use the Qt UNICODE representation: QString. Additionally, there
|
||||
are methods to set the foreground and background colors using
|
||||
QColor.
|
||||
|
||||
* Removed redundant insertion of display list index in the glyph display
|
||||
list cache.
|
||||
|
||||
* Removed memory leak on deletion of face. Was not freeing the glyph
|
||||
display lists.
|
||||
|
||||
* Added check for validity of FT_Face in OGLFT::Face subclasses before
|
||||
proceeding with subclass initiliation.
|
||||
|
||||
* For now at least, tessellation of straight lines is also broken into
|
||||
segments so that the triangles produced by gluTess* are (slightly)
|
||||
more regular.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/liboglft/OGLFT.h:
|
||||
Fix issue with compiling under older version (2.95) of GCC g++.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/liboglft/OGLFT.cpp:
|
||||
Add extra case statements to silence compiler warning.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/liboglft/OGLFT.h:
|
||||
Fix bug in BoundingBox auto-increment operator.
|
||||
|
||||
2002-02-05 allen@llama.lignumcomputing.org <allen@llama>
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/doc/documentation.dox:
|
||||
Update copyright date and SourceForge logo reference.
|
||||
|
||||
2002-02-04 allen@llama.lignumcomputing.org <allen@llama>
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/NEWS, /home/allen/cvsroot/lignumCAD/OGLFT/configure.ac, /home/allen/cvsroot/lignumCAD/OGLFT/doc/Doxyfile:
|
||||
Update to 0.6.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/NEWS:
|
||||
Comment on "Changes to improve compilation on SGI."
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/liboglft/OGLFT.h, /home/allen/cvsroot/lignumCAD/OGLFT/liboglft/OGLFT.cpp:
|
||||
Changes to improve compilation on SGI.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/liboglft/OGLFT.h:
|
||||
Don't try to include mpatrol header if built without mpatrol.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/configure.ac:
|
||||
* Make sure to check for libm first.
|
||||
|
||||
* Do not continue build if proper freetype headers are not found.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/tests/demo2.cpp:
|
||||
stdio.h not included if mpatrol is undefined.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/tests/Makefile.am:
|
||||
Don't include moc_*.cpp files in distribution.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/tests/vignette.h, /home/allen/cvsroot/lignumCAD/OGLFT/tests/speedtest.h:
|
||||
Missing definition of exit() when built in "dist" mode (?)
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/ChangeLog:
|
||||
Reran EMACS regeneration command.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/NEWS:
|
||||
Add note about already open FT_Face.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/doc/html/classOGLFT_1_1ColorTess.html, /home/allen/cvsroot/lignumCAD/OGLFT/doc/html/classOGLFT_1_1ColorTess-members.html, /home/allen/cvsroot/lignumCAD/OGLFT/doc/html/classOGLFT_1_1TextureTess.html, /home/allen/cvsroot/lignumCAD/OGLFT/doc/html/classOGLFT_1_1TextureTess-members.html:
|
||||
New structures.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/ChangeLog, /home/allen/cvsroot/lignumCAD/OGLFT/Makefile.in, /home/allen/cvsroot/lignumCAD/OGLFT/NEWS:
|
||||
Updates for version 0.5.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/doc/Doxyfile:
|
||||
Updated version number.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/doc/documentation.dox:
|
||||
Updates for version 0.5.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/tests/demo2.cpp:
|
||||
Demo of using an already open FT_Face.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/tests/demo3.cpp: The spiffy demo.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/tests/Makefile.am:
|
||||
Renamed demo2 and demo3.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/liboglft/OGLFT.cpp, /home/allen/cvsroot/lignumCAD/OGLFT/liboglft/OGLFT.h:
|
||||
Add a constructor where the FT_Face is already open.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/README:
|
||||
Updated compilation instructions to better describe configure options.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/Makefile.am:
|
||||
Add target for the bzip distribution.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/tests/Makefile.am:
|
||||
Added demo2 texture.png to distribution.
|
||||
|
||||
* /home/allen/cvsroot/lignumCAD/OGLFT/tests/demo2.cpp:
|
||||
Run the per glyph display text in the other direction.
|
||||
|
||||
2002-02-04 Allen Barnett <allen@localhost.localdomain>
|
||||
|
||||
* NEWS: Comment on "Changes to improve compilation on SGI."
|
||||
|
||||
* liboglft/OGLFT.h, liboglft/OGLFT.cpp:
|
||||
Changes to improve compilation on SGI.
|
||||
|
||||
* liboglft/OGLFT.h:
|
||||
Don't try to include mpatrol header if built without mpatrol.
|
||||
|
||||
* configure.ac: * Make sure to check for libm first.
|
||||
|
||||
* Do not continue build if proper freetype headers are not found.
|
||||
|
||||
* tests/demo2.cpp: stdio.h not included if mpatrol is undefined.
|
||||
|
||||
* tests/Makefile.am: Don't include moc_*.cpp files in distribution.
|
||||
|
||||
* tests/vignette.h, tests/speedtest.h:
|
||||
Missing definition of exit() when built in "dist" mode (?)
|
||||
|
||||
* ChangeLog: Reran EMACS regeneration command.
|
||||
|
||||
* NEWS: Add note about already open FT_Face.
|
||||
|
||||
* doc/Doxyfile: Updated version number.
|
||||
|
||||
* doc/documentation.dox: Updates for version 0.5.
|
||||
|
||||
* tests/demo2.cpp: Demo of using an already open FT_Face.
|
||||
|
||||
* tests/demo3.cpp: The spiffy demo.
|
||||
|
||||
* tests/Makefile.am: Renamed demo2 and demo3.
|
||||
|
||||
* liboglft/OGLFT.cpp, liboglft/OGLFT.h:
|
||||
Add a constructor where the FT_Face is already open.
|
||||
|
||||
* README:
|
||||
Updated compilation instructions to better describe configure options.
|
||||
|
||||
* Makefile.am: Add target for the bzip distribution.
|
||||
|
||||
* tests/Makefile.am: Added demo2 texture.png to distribution.
|
||||
|
||||
* tests/demo2.cpp:
|
||||
Run the per glyph display text in the other direction.
|
||||
|
||||
2002-02-01 Allen Barnett <allen@localhost.localdomain>
|
||||
|
||||
* tests/background00a.png, tests/background00b.png, tests/background00.png, tests/background01.png, tests/background10a.png, tests/background10b.png, tests/background10.png, tests/background11.png, tests/background.png:
|
||||
Background images for demo2.
|
||||
|
||||
* tests/tutorial3.cpp, tests/speedtest.cpp:
|
||||
Accounted for absence of Solid face.
|
||||
|
||||
* configure.ac: Improved GLE checking.
|
||||
|
||||
* tests/demo2.cpp, tests/demo.cpp: Accounted for absence of Solid face.
|
||||
|
||||
* configure.ac: Added an mpatrol configuration option.
|
||||
|
||||
* liboglft/OGLFT.h:
|
||||
Added definitions for Color and Texture callbacks during tessellation.
|
||||
|
||||
* liboglft/OGLFT.cpp: * Added color callback for Face::Outline.
|
||||
|
||||
* Added color and texture callbacks for Face::Filled.
|
||||
|
||||
* Properly set the character rotation reference for all face types.
|
||||
|
||||
* Cleaned up memory leak during GLU tesselation.
|
||||
|
||||
* tests/vignette.h, tests/demo2.cpp: Initial checkin
|
||||
|
||||
2002-02-01 Allen Barnett <allen@localhost.localdomain>
|
||||
|
||||
* tests/background00a.png, tests/background00b.png, tests/background00.png, tests/background01.png, tests/background10a.png, tests/background10b.png, tests/background10.png, tests/background11.png, tests/background.png:
|
||||
Background images for demo2.
|
||||
|
||||
* tests/tutorial3.cpp, tests/speedtest.cpp:
|
||||
Accounted for absence of Solid face.
|
||||
|
||||
* configure.ac: Improved GLE checking.
|
||||
|
||||
* tests/demo2.cpp, tests/demo.cpp: Accounted for absence of Solid face.
|
||||
|
||||
* configure.ac: Added an mpatrol configuration option.
|
||||
|
||||
* liboglft/OGLFT.h:
|
||||
Added definitions for Color and Texture callbacks during tessellation.
|
||||
|
||||
* liboglft/OGLFT.cpp: * Added color callback for Face::Outline.
|
||||
|
||||
* Added color and texture callbacks for Face::Filled.
|
||||
|
||||
* Properly set the character rotation reference for all face types.
|
||||
|
||||
* Cleaned up memory leak during GLU tesselation.
|
||||
|
||||
* tests/vignette.h, tests/demo2.cpp: Initial checkin
|
||||
|
||||
2002-01-29 Allen Barnett <allen@localhost.localdomain>
|
||||
|
||||
* liboglft/OGLFT.cpp: Moved config.h to the main library source .
|
||||
|
||||
* liboglft/Makefile.am: Be sure to install the library header file.
|
||||
|
||||
* liboglft/OGLFT.h: Moved config.h to the main library source.
|
||||
|
||||
* tests/tutorial3.cpp, tests/tutorial2.cpp, tests/tutorial1.cpp, tests/speedtest.cpp:
|
||||
Added revsion control keyword (Id).
|
||||
|
||||
* tests/speedtest.cpp, tests/speedtest.h:
|
||||
Reorganized a little to help automake deal with .moc files.
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
Copyright 1994, 1995, 1996, 1999, 2000, 2001 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
These are generic installation instructions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. (Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.)
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You only need
|
||||
`configure.ac' if you want to change it or regenerate `configure' using
|
||||
a newer version of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system. If you're
|
||||
using `csh' on an old version of System V, you might need to type
|
||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
||||
`configure' itself.
|
||||
|
||||
Running `configure' takes awhile. While running, it prints some
|
||||
messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the `configure' script does not know about. Run `./configure --help'
|
||||
for details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for variables by setting
|
||||
them in the environment. You can do that on the command line like this:
|
||||
|
||||
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you must use a version of `make' that
|
||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
If you have to use a `make' that does not support the `VPATH'
|
||||
variable, you have to compile the package for one architecture at a
|
||||
time in the source code directory. After you have installed the
|
||||
package for one architecture, use `make distclean' before reconfiguring
|
||||
for another architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' will install the package's files in
|
||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
||||
installation prefix other than `/usr/local' by giving `configure' the
|
||||
option `--prefix=PATH'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
give `configure' the option `--exec-prefix=PATH', the package will use
|
||||
PATH as the prefix for installing programs and libraries.
|
||||
Documentation and other data files will still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=PATH' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out
|
||||
automatically, but needs to determine by the type of host the package
|
||||
will run on. Usually `configure' can figure that out, but if it prints
|
||||
a message saying it cannot guess the host type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the host type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the `--target=TYPE' option to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the host
|
||||
platform (i.e., that on which the generated programs will eventually be
|
||||
run) with `--host=TYPE'. In this case, you should also specify the
|
||||
build platform with `--build=TYPE', because, in this case, it may not
|
||||
be possible to guess the build platform (it sometimes involves
|
||||
compiling and running simple test programs, and this can't be done if
|
||||
the compiler is a cross compiler).
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share,
|
||||
you can create a site shell script called `config.site' that gives
|
||||
default values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
will cause the specified gcc to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
New in OGLFT version 0.8
|
||||
|
||||
* Added the ability to draw numbers with a format à la printf.
|
||||
There is also a format, %p, which will draw the number as
|
||||
a fraction.
|
||||
|
||||
* Updated the source to be compilable with G++ 3.
|
||||
|
||||
* Added an (untested) Qt project for OSs which don't support
|
||||
autoconf.
|
||||
|
||||
* Note: FreeType versions 2.0.9 through 2.1.2 contain a bug which
|
||||
prevents rotated text from being rendered correctly.
|
||||
|
||||
New in OGLFT version 0.7
|
||||
|
||||
* Fixed another memory leak when deleting a Face which had compiled
|
||||
its glyphs into display lists (the default behavior).
|
||||
|
||||
* Added the ability to render UNICODE glyphs using Qt QStrings.
|
||||
|
||||
* Added the ability to use mulitple FT_Faces in a single OGLFT::Face
|
||||
so that you can cover more UNICODE points by combining fonts.
|
||||
|
||||
New in OGLFT version 0.6
|
||||
|
||||
Updates include:
|
||||
|
||||
* Fixed a pervasive memory leak (must call FT_Done_Glyph after each
|
||||
call to FT_Get_Glyph).
|
||||
|
||||
* measure() now queries the OpenGL view and calls gluUnProject to
|
||||
compute accurate glyph sizes.
|
||||
|
||||
* Autoconf-enabled.
|
||||
|
||||
* There is a user color callback for drawing the Outline face and
|
||||
color and texture coordinate callbacks for the Filled face.
|
||||
|
||||
* Can pass an already open FreeType FT_Face to a rendering style.
|
||||
|
||||
* Changes to improve compilation on the SGI.
|
||||
|
||||
;;;Local variables: ***
|
||||
;;;mode: text ***
|
||||
;;;End: ***
|
||||
@@ -0,0 +1,52 @@
|
||||
OGLFT Version 0.8
|
||||
|
||||
OGLFT is a library for drawing text in OpenGL. It usees the FreeType 2
|
||||
library to extract information from font files on your system. OGLFT
|
||||
can handle any of the files which FreeType can read, both vector and
|
||||
bitmapped (although currently the bitmap routines are not implemented).
|
||||
|
||||
The software is available from www.sf.net/project/oglft.
|
||||
|
||||
The documentation is in ./doc/html/index.html.
|
||||
|
||||
The mailing list is oglft-devel@lists.sourceforge.net.
|
||||
|
||||
A couple of installation notes:
|
||||
|
||||
OGLFT depends on the GLE Tubing and Extrusion library to create solid
|
||||
characters. If you don't have this library (or don't want solid
|
||||
glyphs), you can disable this feature with:
|
||||
|
||||
./configure --disable-solid
|
||||
|
||||
If the configure script can't find the GLE library and header files,
|
||||
it is disabled automatically.
|
||||
|
||||
UNICODE character rendering, Demo3 and the performance test code
|
||||
depend on the Qt library. You can disable them with:
|
||||
|
||||
./configure --disable-qt
|
||||
|
||||
Note that the configure script depends on finding the environment
|
||||
variable QTDIR in order to locate the headers and library for Qt (if
|
||||
not disabled). If the configure script can't successfully build a
|
||||
simple Qt app, Qt is disabled automatically.
|
||||
|
||||
'make check' builds the test programs in the tests/ directory.
|
||||
|
||||
There is also a (mostly untested) Qt project file from which it may be
|
||||
possible to generate a Makefile for operating systems for which
|
||||
autoconf is not supported. Edit the files ./OGLFT/OGLFT.pro and
|
||||
./tests/tests.pro to change the values to those appropriate for your
|
||||
operating system. Generate the library and the test program by doing a
|
||||
"make install" (this will actually only copy the library to the ./lib
|
||||
directory).
|
||||
|
||||
---------------------------------------------------------------------
|
||||
lignum Computing, Inc., July, 2002
|
||||
oglft@lignumcomputing.com
|
||||
|
||||
|
||||
;;;Local variables: ***
|
||||
;;;mode: text ***
|
||||
;;;End: ***
|
||||
@@ -0,0 +1,45 @@
|
||||
CMAKE_MINIMUM_REQUIRED (VERSION 2.6)
|
||||
|
||||
FIND_PACKAGE ( FreeType2 REQUIRED )
|
||||
|
||||
FILE( GLOB sources *.cpp )
|
||||
IF( DESIRED_QT_VERSION EQUAL 3)
|
||||
INCLUDE_DIRECTORIES( ${QT_INCLUDE_DIR} )
|
||||
ELSEIF( DESIRED_QT_VERSION EQUAL 4 )
|
||||
INCLUDE_DIRECTORIES( ${QT_QTCORE_INCLUDE_DIR} )
|
||||
INCLUDE_DIRECTORIES( ${QT_QTGUI_INCLUDE_DIR} )
|
||||
ENDIF( DESIRED_QT_VERSION EQUAL 3)
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${FREETYPE2_INCLUDE_DIR}
|
||||
)
|
||||
INCLUDE_DIRECTORIES( ${PROJECT_BINARY_DIR} )
|
||||
CONFIGURE_FILE(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/OGLFT.h.cmake"
|
||||
"${PROJECT_BINARY_DIR}/OGLFT.h"
|
||||
)
|
||||
|
||||
IF( WIN32 )
|
||||
ADD_DEFINITIONS( -DOGLFT_BUILD )
|
||||
ENDIF( WIN32 )
|
||||
|
||||
ADD_LIBRARY( oglft STATIC ${sources} )
|
||||
TARGET_LINK_LIBRARIES(
|
||||
oglft
|
||||
${FREETYPE2_LIBRARIES}
|
||||
${OPENGL_LIBRARIES}
|
||||
)
|
||||
|
||||
INSTALL(
|
||||
TARGETS oglft
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
COMPONENT libraries
|
||||
)
|
||||
|
||||
INSTALL(
|
||||
FILES "${PROJECT_BINARY_DIR}/OGLFT.h"
|
||||
DESTINATION include/OGLFT
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
|
||||
COMPONENT headers
|
||||
)
|
||||
@@ -0,0 +1,117 @@
|
||||
FIND_PACKAGE( GLUT )
|
||||
|
||||
LINK_LIBRARIES( oglft ${FREETYPE2_LIBRARIES})
|
||||
|
||||
INCLUDE_DIRECTORIES( ${PROJECT_BINARY_DIR} )
|
||||
INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR} )
|
||||
INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} )
|
||||
INCLUDE_DIRECTORIES( ${FREETYPE2_INCLUDE_DIR}
|
||||
${FREETYPE2_INCLUDE_DIR}/freetype2
|
||||
)
|
||||
INCLUDE_DIRECTORIES( ${GLUT_INCLUDE_DIR} )
|
||||
IF( ENABLE_QT )
|
||||
IF( DESIRED_QT_VERSION EQUAL 3)
|
||||
INCLUDE_DIRECTORIES( ${QT_INCLUDE_DIR} )
|
||||
LINK_LIBRARIES( oglft ${FREETYPE2_LIBRARIES} ${QT_LIBRARIES} )
|
||||
ELSEIF( DESIRED_QT_VERSION EQUAL 4 )
|
||||
INCLUDE_DIRECTORIES( ${QT_QTCORE_INCLUDE_DIR} )
|
||||
INCLUDE_DIRECTORIES( ${QT_QTGUI_INCLUDE_DIR} )
|
||||
INCLUDE_DIRECTORIES( ${QT_QTOPENGL_INCLUDE_DIR} )
|
||||
LINK_LIBRARIES( oglft ${FREETYPE2_LIBRARIES} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} )
|
||||
ENDIF( DESIRED_QT_VERSION EQUAL 3)
|
||||
ENDIF( ENABLE_QT )
|
||||
|
||||
ADD_EXECUTABLE(
|
||||
tutorial1
|
||||
tutorial1.cpp
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES(
|
||||
tutorial1
|
||||
${GLUT_LIBRARIES}
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(
|
||||
tutorial2
|
||||
tutorial2.cpp
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES(
|
||||
tutorial2
|
||||
${GLUT_LIBRARIES}
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(
|
||||
tutorial3
|
||||
tutorial3.cpp
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES(
|
||||
tutorial3
|
||||
${GLUT_LIBRARIES}
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(
|
||||
tutorial3
|
||||
tutorial3.cpp
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES(
|
||||
tutorial3
|
||||
${GLUT_LIBRARIES}
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(
|
||||
demo
|
||||
demo.cpp
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES(
|
||||
demo
|
||||
${GLUT_LIBRARIES}
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(
|
||||
demo2
|
||||
demo2.cpp
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES(
|
||||
demo2
|
||||
${GLUT_LIBRARIES}
|
||||
)
|
||||
|
||||
IF( ENABLE_QT )
|
||||
IF( DESIRED_QT_VERSION EQUAL 3 )
|
||||
KDE3_AUTOMOC( demo3.cpp speedtest.cpp )
|
||||
ELSEIF( DESIRED_QT_VERSION EQUAL 4 )
|
||||
QT4_AUTOMOC( demo3.cpp speedtest.cpp )
|
||||
ENDIF( DESIRED_QT_VERSION EQUAL 3 )
|
||||
ADD_EXECUTABLE(
|
||||
demo3
|
||||
demo3.cpp
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES(
|
||||
demo3
|
||||
${OPENGL_LIBRARIES}
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(
|
||||
speedtest
|
||||
speedtest.cpp
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES(
|
||||
speedtest
|
||||
${OPENGL_LIBRARIES}
|
||||
)
|
||||
ENDIF( ENABLE_QT )
|
||||
|
||||
# Copy some files needed by demo3 into the tests directory.
|
||||
FILE( GLOB images *.png )
|
||||
FOREACH( test_png ${images} )
|
||||
GET_FILENAME_COMPONENT( png_file ${test_png} NAME )
|
||||
CONFIGURE_FILE( ${test_png}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${png_file}" COPYONLY )
|
||||
ENDFOREACH( test_png ${images} )
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Demo3UnicodeExample.h: Sample font for demo3 example.
|
||||
* Copyright (C) 2002 lignum Computing, Inc. <oglft@lignumcomputing.com>
|
||||
* $Id$
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
FT_Byte Demo3UnicodeExample_ttf[] = {
|
||||
0,1,0,0,0,11,0,128,0,3,0,48,79,83,47,50,
|
||||
83,120,128,90,0,0,0,188,0,0,0,86,99,109,97,112,
|
||||
135,81,49,45,0,0,1,20,0,0,1,114,99,118,116,32,
|
||||
5,238,9,153,0,0,2,136,0,0,0,36,103,108,121,102,
|
||||
105,160,31,169,0,0,2,172,0,0,4,178,104,101,97,100,
|
||||
212,135,107,129,0,0,7,96,0,0,0,54,104,104,101,97,
|
||||
6,249,3,88,0,0,7,152,0,0,0,36,104,109,116,120,
|
||||
20,76,1,64,0,0,7,188,0,0,0,40,108,111,99,97,
|
||||
6,150,5,39,0,0,7,228,0,0,0,22,109,97,120,112,
|
||||
0,78,0,250,0,0,7,252,0,0,0,32,110,97,109,101,
|
||||
88,93,109,50,0,0,8,28,0,0,3,72,112,111,115,116,
|
||||
11,139,233,133,0,0,11,100,0,0,0,100,0,1,3,232,
|
||||
1,144,0,5,0,12,0,200,0,200,0,0,0,200,0,200,
|
||||
0,200,0,0,0,200,0,49,1,2,0,0,2,0,5,3,
|
||||
0,0,0,0,0,0,0,0,1,131,0,0,0,96,0,0,
|
||||
0,0,0,0,0,0,80,102,69,100,0,64,0,0,34,43,
|
||||
3,164,255,52,0,0,3,164,0,204,0,0,0,1,0,0,
|
||||
0,0,0,0,0,0,0,2,0,3,0,1,0,0,0,20,
|
||||
0,1,0,0,0,0,0,108,0,4,0,88,0,0,0,18,
|
||||
0,16,0,3,0,2,3,169,3,195,3,200,33,38,33,146,
|
||||
34,7,34,25,34,43,255,255,0,0,3,169,3,195,3,200,
|
||||
33,38,33,146,34,7,34,25,34,43,255,255,252,90,252,65,
|
||||
252,61,222,221,222,116,222,0,221,239,221,222,0,1,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,1,6,0,0,1,0,0,0,0,0,0,0,1,3,
|
||||
0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,33,2,121,0,0,0,86,
|
||||
0,83,1,30,0,100,0,12,0,74,2,25,0,92,2,222,
|
||||
0,90,0,50,3,176,0,41,0,102,0,78,0,2,0,33,
|
||||
0,0,1,110,2,154,0,3,0,7,0,46,177,1,0,47,
|
||||
60,178,7,4,0,237,50,177,6,5,220,60,178,3,2,0,
|
||||
237,50,0,177,3,0,47,60,178,5,4,0,237,50,178,7,
|
||||
6,1,252,60,178,1,2,0,237,50,51,17,33,17,37,33,
|
||||
17,33,33,1,77,254,212,1,11,254,245,2,154,253,102,33,
|
||||
2,88,0,1,0,48,0,0,2,206,2,234,0,38,0,137,
|
||||
0,177,20,2,63,176,21,47,176,37,51,176,38,51,177,0,
|
||||
3,237,177,1,3,237,177,18,3,237,177,19,3,237,176,6,
|
||||
47,176,28,51,176,29,51,176,30,51,177,10,4,237,1,176,
|
||||
0,47,176,38,51,177,36,5,237,177,37,5,237,176,2,47,
|
||||
176,3,51,176,4,51,176,5,51,177,6,6,237,177,33,6,
|
||||
237,177,34,6,237,177,35,6,237,176,21,176,36,16,222,176,
|
||||
22,50,177,19,5,237,177,20,5,237,176,23,176,34,16,222,
|
||||
176,24,50,176,25,50,177,15,6,237,177,16,6,237,177,17,
|
||||
6,237,177,40,16,16,204,48,49,55,51,38,53,39,54,55,
|
||||
54,55,54,23,22,23,22,23,22,21,20,7,51,21,33,53,
|
||||
54,61,1,54,39,38,7,38,7,49,6,23,20,23,21,33,
|
||||
48,160,151,1,1,101,24,28,74,120,92,58,104,36,16,152,
|
||||
160,254,226,178,3,71,63,95,110,66,53,2,177,254,226,86,
|
||||
127,182,1,165,99,23,17,50,5,4,37,65,127,55,61,182,
|
||||
128,86,81,83,216,2,127,82,72,1,2,96,78,104,220,85,
|
||||
81,0,0,2,0,34,255,243,2,98,2,32,0,19,0,35,
|
||||
0,98,0,177,8,7,63,176,9,47,176,10,51,177,27,8,
|
||||
237,177,28,8,237,177,29,8,237,177,0,9,63,176,19,47,
|
||||
177,1,8,237,177,2,8,237,1,176,13,47,176,14,51,176,
|
||||
15,51,176,16,51,177,23,10,237,177,24,10,237,177,25,10,
|
||||
237,176,31,176,24,16,222,176,32,50,176,33,50,177,3,10,
|
||||
237,177,4,10,237,177,5,10,237,177,6,10,237,177,37,5,
|
||||
16,204,48,49,1,21,35,22,21,23,20,7,6,35,34,47,
|
||||
1,38,61,1,52,55,54,23,7,6,7,6,23,6,23,22,
|
||||
23,54,55,54,39,52,39,38,2,98,145,66,1,73,68,108,
|
||||
108,66,5,70,73,106,154,87,94,40,22,2,2,81,33,44,
|
||||
102,38,19,1,75,35,2,19,73,62,130,1,143,67,67,65,
|
||||
5,70,136,2,141,68,96,40,63,2,87,49,65,134,48,20,
|
||||
1,1,95,47,61,130,50,23,0,1,0,61,255,52,2,157,
|
||||
2,19,0,34,0,118,0,176,26,47,176,27,51,177,0,11,
|
||||
237,177,1,11,237,177,9,11,237,177,10,11,237,177,17,11,
|
||||
237,177,18,11,237,1,176,0,47,176,33,51,176,34,51,177,
|
||||
1,12,237,177,2,12,237,177,3,12,237,176,8,176,1,16,
|
||||
222,176,9,50,176,27,50,176,28,50,177,10,12,237,177,11,
|
||||
12,237,177,25,12,237,177,26,12,237,176,14,176,10,16,222,
|
||||
176,15,50,176,16,50,176,17,50,177,18,12,237,177,19,12,
|
||||
237,177,20,12,237,177,36,18,16,204,48,49,19,51,17,22,
|
||||
23,22,23,22,23,17,51,17,54,55,54,61,1,17,51,17,
|
||||
6,7,6,7,6,7,21,35,53,38,39,38,39,38,39,61,
|
||||
89,2,19,13,29,39,68,90,124,32,13,89,1,24,20,51,
|
||||
59,103,90,138,63,43,9,5,1,2,19,254,250,97,34,25,
|
||||
20,26,3,1,211,254,45,4,86,38,76,1,1,6,254,253,
|
||||
122,47,39,35,38,3,192,192,5,68,48,55,32,76,0,1,
|
||||
0,39,0,78,3,216,1,182,0,18,0,37,0,176,11,47,
|
||||
176,12,51,177,13,13,237,177,14,13,237,1,176,12,47,176,
|
||||
13,51,177,3,14,237,177,4,14,237,177,20,3,16,204,48,
|
||||
49,1,22,31,1,21,6,7,6,7,35,54,55,33,53,33,
|
||||
38,39,53,39,3,10,91,64,51,86,76,19,26,39,47,52,
|
||||
252,227,3,29,51,20,26,1,182,98,41,27,23,44,78,20,
|
||||
29,101,54,51,66,36,1,51,0,2,0,14,0,0,2,103,
|
||||
2,182,0,2,0,5,0,23,0,176,3,47,176,5,51,177,
|
||||
0,15,237,177,1,15,237,1,177,7,1,47,204,48,49,19,
|
||||
33,1,3,27,1,14,2,88,254,198,168,200,220,2,182,253,
|
||||
74,2,140,254,29,1,227,0,0,1,0,92,1,53,0,195,
|
||||
1,156,0,3,0,37,0,176,0,47,176,3,51,177,1,16,
|
||||
237,177,2,16,237,1,176,0,47,176,1,51,177,2,16,237,
|
||||
177,3,16,237,177,5,2,16,204,48,49,19,53,51,21,92,
|
||||
103,1,54,102,102,0,0,1,255,255,255,145,1,25,3,164,
|
||||
0,46,0,29,176,0,47,176,26,51,176,38,51,176,45,51,
|
||||
176,46,51,177,16,17,237,177,21,17,237,177,22,17,237,48,
|
||||
49,27,1,54,55,54,55,54,23,22,21,22,7,6,35,34,
|
||||
39,38,7,6,31,1,22,7,3,6,7,6,39,38,39,38,
|
||||
55,54,55,54,23,22,23,22,63,1,54,39,38,39,38,17,
|
||||
100,9,9,70,14,16,31,22,9,1,28,9,10,17,21,18,
|
||||
15,8,1,4,20,1,8,4,41,25,43,25,17,21,6,3,
|
||||
9,20,29,11,7,22,15,1,8,5,1,1,18,1,218,1,
|
||||
10,155,29,6,2,1,28,13,14,35,13,4,18,19,15,9,
|
||||
17,72,251,86,254,222,147,52,35,1,1,16,20,35,15,9,
|
||||
22,11,5,8,24,14,1,15,48,12,8,158,1,1,0,0,
|
||||
0,1,0,0,0,0,0,0,248,61,157,109,95,15,60,245,
|
||||
0,19,3,232,0,0,0,0,184,197,19,226,0,0,0,0,
|
||||
184,197,19,226,255,255,255,52,3,216,3,164,0,0,0,8,
|
||||
0,2,0,0,0,0,0,0,0,1,0,0,3,32,255,56,
|
||||
0,0,4,11,255,255,0,10,3,216,0,1,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,10,1,176,0,33,
|
||||
0,0,0,0,1,77,0,0,2,248,0,48,2,142,0,34,
|
||||
2,236,0,61,4,11,0,39,2,136,0,14,1,38,0,92,
|
||||
1,35,255,255,0,0,0,43,0,43,0,43,0,171,1,22,
|
||||
1,137,1,190,1,222,1,253,2,89,0,0,0,1,0,0,
|
||||
0,10,0,47,0,2,0,0,0,0,0,2,0,0,0,64,
|
||||
0,1,0,0,0,64,0,137,0,0,0,0,0,0,0,21,
|
||||
1,2,0,1,0,0,0,0,0,0,0,65,0,0,0,1,
|
||||
0,0,0,0,0,1,0,21,0,66,0,1,0,0,0,0,
|
||||
0,2,0,7,0,88,0,1,0,0,0,0,0,3,0,47,
|
||||
0,96,0,1,0,0,0,0,0,4,0,21,0,144,0,1,
|
||||
0,0,0,0,0,5,0,7,0,166,0,1,0,0,0,0,
|
||||
0,6,0,19,0,174,0,0,0,3,0,0,0,0,0,130,
|
||||
0,194,0,0,0,3,0,0,0,1,0,42,1,70,0,0,
|
||||
0,3,0,0,0,2,0,14,1,114,0,0,0,3,0,0,
|
||||
0,3,0,94,1,130,0,0,0,3,0,0,0,4,0,42,
|
||||
1,226,0,0,0,3,0,0,0,5,0,14,2,14,0,0,
|
||||
0,3,0,0,0,6,0,38,2,30,0,3,0,1,4,9,
|
||||
0,0,0,130,0,194,0,3,0,1,4,9,0,1,0,42,
|
||||
1,70,0,3,0,1,4,9,0,2,0,14,1,114,0,3,
|
||||
0,1,4,9,0,3,0,94,1,130,0,3,0,1,4,9,
|
||||
0,4,0,42,1,226,0,3,0,1,4,9,0,5,0,14,
|
||||
2,14,0,3,0,1,4,9,0,6,0,38,2,30,67,114,
|
||||
101,97,116,101,100,32,98,121,32,65,108,108,101,110,32,66,
|
||||
97,114,110,101,116,116,32,119,105,116,104,32,80,102,97,69,
|
||||
100,105,116,32,49,46,48,32,40,104,116,116,112,58,47,47,
|
||||
112,102,97,101,100,105,116,46,115,102,46,110,101,116,41,0,
|
||||
68,101,109,111,51,32,85,110,105,99,111,100,101,32,69,120,
|
||||
97,109,112,108,101,0,82,101,103,117,108,97,114,0,80,102,
|
||||
97,69,100,105,116,32,49,46,48,32,58,32,68,101,109,111,
|
||||
51,32,85,110,105,99,111,100,101,32,69,120,97,109,112,108,
|
||||
101,32,58,32,50,53,45,50,45,50,48,55,50,0,68,101,
|
||||
109,111,51,32,85,110,105,99,111,100,101,32,69,120,97,109,
|
||||
112,108,101,0,48,48,49,46,48,48,48,0,68,101,109,111,
|
||||
51,85,110,105,99,111,100,101,69,120,97,109,112,108,101,0,
|
||||
0,67,0,114,0,101,0,97,0,116,0,101,0,100,0,32,
|
||||
0,98,0,121,0,32,0,65,0,108,0,108,0,101,0,110,
|
||||
0,32,0,66,0,97,0,114,0,110,0,101,0,116,0,116,
|
||||
0,32,0,119,0,105,0,116,0,104,0,32,0,80,0,102,
|
||||
0,97,0,69,0,100,0,105,0,116,0,32,0,49,0,46,
|
||||
0,48,0,32,0,40,0,104,0,116,0,116,0,112,0,58,
|
||||
0,47,0,47,0,112,0,102,0,97,0,101,0,100,0,105,
|
||||
0,116,0,46,0,115,0,102,0,46,0,110,0,101,0,116,
|
||||
0,41,0,0,0,68,0,101,0,109,0,111,0,51,0,32,
|
||||
0,85,0,110,0,105,0,99,0,111,0,100,0,101,0,32,
|
||||
0,69,0,120,0,97,0,109,0,112,0,108,0,101,0,0,
|
||||
0,82,0,101,0,103,0,117,0,108,0,97,0,114,0,0,
|
||||
0,80,0,102,0,97,0,69,0,100,0,105,0,116,0,32,
|
||||
0,49,0,46,0,48,0,32,0,58,0,32,0,68,0,101,
|
||||
0,109,0,111,0,51,0,32,0,85,0,110,0,105,0,99,
|
||||
0,111,0,100,0,101,0,32,0,69,0,120,0,97,0,109,
|
||||
0,112,0,108,0,101,0,32,0,58,0,32,0,50,0,53,
|
||||
0,45,0,50,0,45,0,50,0,48,0,55,0,50,0,0,
|
||||
0,68,0,101,0,109,0,111,0,51,0,32,0,85,0,110,
|
||||
0,105,0,99,0,111,0,100,0,101,0,32,0,69,0,120,
|
||||
0,97,0,109,0,112,0,108,0,101,0,0,0,48,0,48,
|
||||
0,49,0,46,0,48,0,48,0,48,0,0,0,68,0,101,
|
||||
0,109,0,111,0,51,0,85,0,110,0,105,0,99,0,111,
|
||||
0,100,0,101,0,69,0,120,0,97,0,109,0,112,0,108,
|
||||
0,101,0,0,0,2,0,0,0,0,0,0,255,156,0,50,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,10,0,0,0,1,0,2,1,2,1,3,
|
||||
1,4,1,5,1,6,1,7,0,156,7,117,110,105,48,51,
|
||||
65,57,5,115,105,103,109,97,3,112,115,105,10,97,114,114,
|
||||
111,119,114,105,103,104,116,8,103,114,97,100,105,101,110,116,
|
||||
7,117,110,105,50,50,49,57,
|
||||
};
|
||||
const int Demo3UnicodeExample_ttf_size = sizeof( Demo3UnicodeExample_ttf );
|
||||
@@ -0,0 +1,949 @@
|
||||
SplineFontDB: 1.0
|
||||
FontName: Demo3UnicodeExample
|
||||
FullName: Demo3 Unicode Example
|
||||
FamilyName: Demo3 Unicode Example
|
||||
Weight: Medium
|
||||
Copyright: Created by Allen Barnett with PfaEdit 1.0 (http://pfaedit.sf.net)
|
||||
Version: 001.000
|
||||
ItalicAngle: 0
|
||||
UnderlinePosition: -100
|
||||
UnderlineWidth: 50
|
||||
Ascent: 800
|
||||
Descent: 200
|
||||
FSType: 12
|
||||
PfmFamily: 17
|
||||
TTFWeight: 400
|
||||
TTFWidth: 5
|
||||
Panose: 2 0 5 3 0 0 0 0 0 0
|
||||
Encoding: 26
|
||||
DisplaySize: -24
|
||||
AntiAlias: 1
|
||||
BeginChars: 65536 263
|
||||
StartChar: space
|
||||
Encoding: 32 32
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: exclam
|
||||
Encoding: 33 33
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: quotedbl
|
||||
Encoding: 34 34
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: numbersign
|
||||
Encoding: 35 35
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: dollar
|
||||
Encoding: 36 36
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: percent
|
||||
Encoding: 37 37
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: ampersand
|
||||
Encoding: 38 38
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: quotesingle
|
||||
Encoding: 39 39
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: parenleft
|
||||
Encoding: 40 40
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: parenright
|
||||
Encoding: 41 41
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: asterisk
|
||||
Encoding: 42 42
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: plus
|
||||
Encoding: 43 43
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: comma
|
||||
Encoding: 44 44
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: hyphen
|
||||
Encoding: 45 45
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: period
|
||||
Encoding: 46 46
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: slash
|
||||
Encoding: 47 47
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: zero
|
||||
Encoding: 48 48
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: one
|
||||
Encoding: 49 49
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: two
|
||||
Encoding: 50 50
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: three
|
||||
Encoding: 51 51
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: four
|
||||
Encoding: 52 52
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: five
|
||||
Encoding: 53 53
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: six
|
||||
Encoding: 54 54
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: seven
|
||||
Encoding: 55 55
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: eight
|
||||
Encoding: 56 56
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: nine
|
||||
Encoding: 57 57
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: colon
|
||||
Encoding: 58 58
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: semicolon
|
||||
Encoding: 59 59
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: less
|
||||
Encoding: 60 60
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: equal
|
||||
Encoding: 61 61
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: greater
|
||||
Encoding: 62 62
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: question
|
||||
Encoding: 63 63
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: at
|
||||
Encoding: 64 64
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: A
|
||||
Encoding: 65 65
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: B
|
||||
Encoding: 66 66
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: C
|
||||
Encoding: 67 67
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: D
|
||||
Encoding: 68 68
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: E
|
||||
Encoding: 69 69
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: F
|
||||
Encoding: 70 70
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: G
|
||||
Encoding: 71 71
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: H
|
||||
Encoding: 72 72
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: I
|
||||
Encoding: 73 73
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: J
|
||||
Encoding: 74 74
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: K
|
||||
Encoding: 75 75
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: L
|
||||
Encoding: 76 76
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: M
|
||||
Encoding: 77 77
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: N
|
||||
Encoding: 78 78
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: O
|
||||
Encoding: 79 79
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: P
|
||||
Encoding: 80 80
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Q
|
||||
Encoding: 81 81
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: R
|
||||
Encoding: 82 82
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: S
|
||||
Encoding: 83 83
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: T
|
||||
Encoding: 84 84
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: U
|
||||
Encoding: 85 85
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: V
|
||||
Encoding: 86 86
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: W
|
||||
Encoding: 87 87
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: X
|
||||
Encoding: 88 88
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Y
|
||||
Encoding: 89 89
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Z
|
||||
Encoding: 90 90
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: bracketleft
|
||||
Encoding: 91 91
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: backslash
|
||||
Encoding: 92 92
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: bracketright
|
||||
Encoding: 93 93
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: asciicircum
|
||||
Encoding: 94 94
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: underscore
|
||||
Encoding: 95 95
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: grave
|
||||
Encoding: 96 96
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: a
|
||||
Encoding: 97 97
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: b
|
||||
Encoding: 98 98
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: c
|
||||
Encoding: 99 99
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: d
|
||||
Encoding: 100 100
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: e
|
||||
Encoding: 101 101
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: f
|
||||
Encoding: 102 102
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: g
|
||||
Encoding: 103 103
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: h
|
||||
Encoding: 104 104
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: i
|
||||
Encoding: 105 105
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: j
|
||||
Encoding: 106 106
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: k
|
||||
Encoding: 107 107
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: l
|
||||
Encoding: 108 108
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: m
|
||||
Encoding: 109 109
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: n
|
||||
Encoding: 110 110
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: o
|
||||
Encoding: 111 111
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: p
|
||||
Encoding: 112 112
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: q
|
||||
Encoding: 113 113
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: r
|
||||
Encoding: 114 114
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: s
|
||||
Encoding: 115 115
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: t
|
||||
Encoding: 116 116
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: u
|
||||
Encoding: 117 117
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: v
|
||||
Encoding: 118 118
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: w
|
||||
Encoding: 119 119
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: x
|
||||
Encoding: 120 120
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: y
|
||||
Encoding: 121 121
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: z
|
||||
Encoding: 122 122
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: braceleft
|
||||
Encoding: 123 123
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: bar
|
||||
Encoding: 124 124
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: braceright
|
||||
Encoding: 125 125
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: asciitilde
|
||||
Encoding: 126 126
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: nonbreakingspace
|
||||
Encoding: 160 160
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: exclamdown
|
||||
Encoding: 161 161
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: cent
|
||||
Encoding: 162 162
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: sterling
|
||||
Encoding: 163 163
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: currency
|
||||
Encoding: 164 164
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: yen
|
||||
Encoding: 165 165
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: brokenbar
|
||||
Encoding: 166 166
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: section
|
||||
Encoding: 167 167
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: dieresis
|
||||
Encoding: 168 168
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: copyright
|
||||
Encoding: 169 169
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: ordfeminine
|
||||
Encoding: 170 170
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: guillemotleft
|
||||
Encoding: 171 171
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: logicalnot
|
||||
Encoding: 172 172
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: softhyphen
|
||||
Encoding: 173 173
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: registered
|
||||
Encoding: 174 174
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: macron
|
||||
Encoding: 175 175
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: degree
|
||||
Encoding: 176 176
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: plusminus
|
||||
Encoding: 177 177
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: twosuperior
|
||||
Encoding: 178 178
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: threesuperior
|
||||
Encoding: 179 179
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: acute
|
||||
Encoding: 180 180
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: mu
|
||||
Encoding: 181 181
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: paragraph
|
||||
Encoding: 182 182
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: periodcentered
|
||||
Encoding: 183 183
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: cedilla
|
||||
Encoding: 184 184
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: onesuperior
|
||||
Encoding: 185 185
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: ordmasculine
|
||||
Encoding: 186 186
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: guillemotright
|
||||
Encoding: 187 187
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: onequarter
|
||||
Encoding: 188 188
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: onehalf
|
||||
Encoding: 189 189
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: threequarters
|
||||
Encoding: 190 190
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: questiondown
|
||||
Encoding: 191 191
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Agrave
|
||||
Encoding: 192 192
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Aacute
|
||||
Encoding: 193 193
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Acircumflex
|
||||
Encoding: 194 194
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Atilde
|
||||
Encoding: 195 195
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Adieresis
|
||||
Encoding: 196 196
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Aring
|
||||
Encoding: 197 197
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: AE
|
||||
Encoding: 198 198
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Ccedilla
|
||||
Encoding: 199 199
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Egrave
|
||||
Encoding: 200 200
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Eacute
|
||||
Encoding: 201 201
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Ecircumflex
|
||||
Encoding: 202 202
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Edieresis
|
||||
Encoding: 203 203
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Igrave
|
||||
Encoding: 204 204
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Iacute
|
||||
Encoding: 205 205
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Icircumflex
|
||||
Encoding: 206 206
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Idieresis
|
||||
Encoding: 207 207
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Eth
|
||||
Encoding: 208 208
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Ntilde
|
||||
Encoding: 209 209
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Ograve
|
||||
Encoding: 210 210
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Oacute
|
||||
Encoding: 211 211
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Ocircumflex
|
||||
Encoding: 212 212
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Otilde
|
||||
Encoding: 213 213
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Odieresis
|
||||
Encoding: 214 214
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: multiply
|
||||
Encoding: 215 215
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Oslash
|
||||
Encoding: 216 216
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Ugrave
|
||||
Encoding: 217 217
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Uacute
|
||||
Encoding: 218 218
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Ucircumflex
|
||||
Encoding: 219 219
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Udieresis
|
||||
Encoding: 220 220
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Yacute
|
||||
Encoding: 221 221
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: Thorn
|
||||
Encoding: 222 222
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: germandbls
|
||||
Encoding: 223 223
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: agrave
|
||||
Encoding: 224 224
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: aacute
|
||||
Encoding: 225 225
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: acircumflex
|
||||
Encoding: 226 226
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: atilde
|
||||
Encoding: 227 227
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: adieresis
|
||||
Encoding: 228 228
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: aring
|
||||
Encoding: 229 229
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: ae
|
||||
Encoding: 230 230
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: ccedilla
|
||||
Encoding: 231 231
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: egrave
|
||||
Encoding: 232 232
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: eacute
|
||||
Encoding: 233 233
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: ecircumflex
|
||||
Encoding: 234 234
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: edieresis
|
||||
Encoding: 235 235
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: igrave
|
||||
Encoding: 236 236
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: iacute
|
||||
Encoding: 237 237
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: icircumflex
|
||||
Encoding: 238 238
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: idieresis
|
||||
Encoding: 239 239
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: eth
|
||||
Encoding: 240 240
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: ntilde
|
||||
Encoding: 241 241
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: ograve
|
||||
Encoding: 242 242
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: oacute
|
||||
Encoding: 243 243
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: ocircumflex
|
||||
Encoding: 244 244
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: otilde
|
||||
Encoding: 245 245
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: odieresis
|
||||
Encoding: 246 246
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: divide
|
||||
Encoding: 247 247
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: oslash
|
||||
Encoding: 248 248
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: ugrave
|
||||
Encoding: 249 249
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: uacute
|
||||
Encoding: 250 250
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: ucircumflex
|
||||
Encoding: 251 251
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: udieresis
|
||||
Encoding: 252 252
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: yacute
|
||||
Encoding: 253 253
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: thorn
|
||||
Encoding: 254 254
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: ydieresis
|
||||
Encoding: 255 255
|
||||
Width: 1000
|
||||
EndChar
|
||||
StartChar: uni03A9
|
||||
Encoding: 937 937
|
||||
Width: 760
|
||||
Flags: W
|
||||
HStem: 0 86.5<55 192 560 711> 662.5 82.6191<368 400>
|
||||
VStem: 48.5 285.5<1 81> 56.5 100.5<368 416> 432.5 285<1 81> 610.5 99<368 416>
|
||||
Fore
|
||||
48.5 86.5 m 1
|
||||
208.5 86.5 l 1
|
||||
107.167 171.167 56.5 274.5 56.5 396.5 c 1
|
||||
56.7101 536.75 118.58 644.249 209.5 699.75 c 1
|
||||
297.509 759.342 465.523 760.85 554.25 703.5 c 1
|
||||
642.338 648.475 711.166 540.692 709.5 396.5 c 1
|
||||
709.5 274.5 658.833 171.167 557.5 86.5 c 1
|
||||
717.5 86.5 l 1
|
||||
717.5 0 l 1
|
||||
432.5 0 l 1
|
||||
432.5 81 l 1
|
||||
551.167 136.333 610.5 236.5 610.5 381.5 c 1
|
||||
613.683 531.395 525.526 663.23 384.5 662.5 c 1
|
||||
242.961 665.005 154.417 531.689 157 386.5 c 1
|
||||
157 239.5 216 137.667 334 81 c 1
|
||||
334 0 l 1
|
||||
48.5 0 l 1
|
||||
48.5 86.5 l 1
|
||||
EndSplineSet
|
||||
MinimumDistance: x5,-1
|
||||
EndChar
|
||||
StartChar: sigma
|
||||
Encoding: 963 963
|
||||
Width: 654
|
||||
Flags: W
|
||||
HStem: -11.9998 73.9998<282 299.31> 458 73<466 594> 468.5 74.5483<280.625 302.587>
|
||||
VStem: 34 92.5<243 265 265.575 298.829> 440 91.5<243 291>
|
||||
Fore
|
||||
609.5 531 m 1
|
||||
609.5 458 l 1
|
||||
465 458 l 1
|
||||
509.333 416.667 531.5 352.333 531.5 265 c 0
|
||||
531.5 170 507.25 100.083 458.75 55.25 c 1
|
||||
367.585 -35.1072 191 -34.6289 104 58 c 1
|
||||
57.333 104.667 34 173.833 34 265.5 c 0
|
||||
34 359.833 58.25 429.667 106.75 475 c 1
|
||||
176.138 537.884 259.745 558.789 367 531 c 1
|
||||
609.5 531 l 1
|
||||
280.5 468.5 m 1
|
||||
180.415 465.592 122.839 382.568 126.5 265 c 1
|
||||
124.033 145.734 177.982 64.8142 282 62 c 1
|
||||
387.637 63.1845 442.118 149.124 440 265.5 c 1
|
||||
439.941 377.605 391.876 470.041 280.5 468.5 c 1
|
||||
EndSplineSet
|
||||
MinimumDistance: x3,-1
|
||||
EndChar
|
||||
StartChar: psi
|
||||
Encoding: 968 968
|
||||
Width: 748
|
||||
Flags: W
|
||||
HStem: -203.5 734.5<320 410>
|
||||
VStem: 61 89.5<244 530> 320 90<-188 -12 65 530> 579 89.5<244 530>
|
||||
Fore
|
||||
61 531 m 1
|
||||
150.5 531 l 1
|
||||
150.5 269 l 1
|
||||
151.992 173.54 157.865 130.981 213.25 92.75 c 1
|
||||
239.083 75.583 274.667 65.833 320 63.5 c 1
|
||||
320 531 l 1
|
||||
410 531 l 1
|
||||
410 63.5 l 1
|
||||
489.519 66.7047 544.824 98.0574 565.75 154.25 c 1
|
||||
574.583 179.75 579 218 579 269 c 2
|
||||
579 531 l 1
|
||||
668.5 531 l 1
|
||||
668.5 272 l 1
|
||||
666.618 133.548 653.5 84.7044 571.5 29.25 c 1
|
||||
532.5 4.08301 478.667 -9.66699 410 -12 c 1
|
||||
410 -203.5 l 1
|
||||
320 -203.5 l 1
|
||||
320 -12 l 1
|
||||
229.595 -8.79161 164.247 11.9517 118.75 61.25 c 1
|
||||
67.0712 119.571 62.4383 155.542 61 272 c 1
|
||||
61 531 l 1
|
||||
EndSplineSet
|
||||
MinimumDistance: x11,-1
|
||||
EndChar
|
||||
StartChar: arrowright
|
||||
Encoding: 8594 8594
|
||||
Width: 1035
|
||||
Flags: W
|
||||
HStem: 233 50.5<55 836>
|
||||
VStem: 39.5 944.5<249 271>
|
||||
Fore
|
||||
777.5 438 m 1
|
||||
848.958 360.788 901.645 310.333 984 271.5 c 1
|
||||
984 249 l 1
|
||||
897.46 204.953 850.008 159.158 777 78.5 c 1
|
||||
738.5 78.5 l 1
|
||||
769.833 145.5 802.667 197 837 233 c 1
|
||||
39.5 233 l 1
|
||||
39.5 283.5 l 1
|
||||
837 283.5 l 1
|
||||
782.642 353.947 781.915 354.515 739.5 438 c 1
|
||||
777.5 438 l 1
|
||||
EndSplineSet
|
||||
MinimumDistance: x1,-1
|
||||
EndChar
|
||||
StartChar: gradient
|
||||
Encoding: 8711 8711
|
||||
Width: 648
|
||||
Flags: W
|
||||
HStem: 652.5 41<134 551>
|
||||
DStem: 14.5 693.5 132.5 652.5 300.5 0 332 169 552 652.5 614.5 693.5 332 169 300.5 0
|
||||
Fore
|
||||
14.5 693.5 m 1
|
||||
614.5 693.5 l 1
|
||||
300.5 0 l 1
|
||||
14.5 693.5 l 1
|
||||
132.5 652.5 m 1
|
||||
332 169 l 1
|
||||
552 652.5 l 1
|
||||
132.5 652.5 l 1
|
||||
EndSplineSet
|
||||
MinimumDistance: x1,-1
|
||||
EndChar
|
||||
StartChar: uni2219
|
||||
Encoding: 8729 8729
|
||||
Width: 294
|
||||
Flags: W
|
||||
HStem: 309.5 102.5<108 194>
|
||||
VStem: 92.5 102.5<325 411>
|
||||
Fore
|
||||
92.5 309.5 m 1
|
||||
92.5 412 l 1
|
||||
195 412 l 1
|
||||
195 309.5 l 1
|
||||
92.5 309.5 l 1
|
||||
EndSplineSet
|
||||
MinimumDistance: x2,-1
|
||||
EndChar
|
||||
StartChar: integral
|
||||
Encoding: 8747 8747
|
||||
Width: 291
|
||||
Flags: W
|
||||
VStem: 100.5 77.8252<327.709 474>
|
||||
Fore
|
||||
100.5 474 m 1
|
||||
109 739.5 l 1
|
||||
114.542 833.138 134.534 923.622 217.5 931.5 c 1
|
||||
247.522 933.096 280.447 905.565 280 878 c 1
|
||||
280.849 848.918 261.127 825.941 234 826 c 1
|
||||
222.333 826 209.667 832 196 844 c 1
|
||||
176.357 863.99 153.522 851.038 156 822 c 1
|
||||
156 808 157.5 783.833 160.5 749.5 c 1
|
||||
184.169 438.285 182.123 484.679 171 123 c 1
|
||||
168.333 24.667 153.333 -41.833 126 -76.5 c 1
|
||||
101.122 -110.714 47.8807 -123.362 16.5 -93 c 1
|
||||
-3.17021 -74.8996 -6.32757 -33.0899 12.75 -13.5 c 1
|
||||
30.257 5.46361 62.8625 4.28698 79.5 -16 c 1
|
||||
93.653 -31.3569 104.804 -38.4598 118 -25 c 1
|
||||
129.244 -4.11259 121.392 22.5244 119 58.5 c 1
|
||||
106.667 163.5 100.5 302 100.5 474 c 1
|
||||
EndSplineSet
|
||||
EndChar
|
||||
EndChars
|
||||
EndSplineFont
|
||||
@@ -0,0 +1,470 @@
|
||||
/*
|
||||
* Demo3UnicodeExample2.h: Additional symbols for demo3 example.
|
||||
* Copyright (C) 2002 lignum Computing, Inc. <oglft@lignumcomputing.com>
|
||||
* $Id$
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
FT_Byte lCSymbols_ttf[] = {
|
||||
0,1,0,0,0,12,0,128,0,3,0,64,79,83,47,50,
|
||||
81,97,77,142,0,0,0,204,0,0,0,86,99,109,97,112,
|
||||
224,46,4,241,0,0,1,36,0,0,1,82,99,118,116,32,
|
||||
4,48,5,221,0,0,2,120,0,0,0,34,103,108,121,102,
|
||||
109,46,45,11,0,0,2,156,0,0,18,254,104,101,97,100,
|
||||
211,187,118,221,0,0,21,156,0,0,0,54,104,104,101,97,
|
||||
6,115,1,120,0,0,21,212,0,0,0,36,104,109,116,120,
|
||||
28,67,1,223,0,0,21,248,0,0,0,100,107,101,114,110,
|
||||
251,84,252,187,0,0,22,92,0,0,0,162,108,111,99,97,
|
||||
51,201,56,104,0,0,23,0,0,0,0,52,109,97,120,112,
|
||||
0,94,1,24,0,0,23,52,0,0,0,32,110,97,109,101,
|
||||
31,28,131,163,0,0,23,84,0,0,3,167,112,111,115,116,
|
||||
142,120,183,88,0,0,26,252,0,0,1,4,0,1,3,232,
|
||||
1,144,0,5,0,12,0,200,0,200,0,0,0,200,0,200,
|
||||
0,200,0,0,0,200,0,49,1,2,0,0,2,0,5,3,
|
||||
0,0,0,0,0,0,0,0,0,3,16,0,0,8,0,0,
|
||||
0,0,0,0,0,0,80,102,69,100,0,64,0,32,224,25,
|
||||
2,234,255,52,0,90,2,234,0,204,0,0,0,1,0,0,
|
||||
0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,28,
|
||||
0,1,0,0,0,0,0,76,0,3,0,1,0,0,0,28,
|
||||
0,4,0,48,0,0,0,8,0,8,0,2,0,0,33,4,
|
||||
224,10,224,25,255,255,0,0,33,4,224,0,224,16,255,255,
|
||||
222,255,32,4,31,255,0,1,0,0,0,0,0,0,0,0,
|
||||
0,0,1,6,0,0,1,0,0,0,0,0,0,0,1,3,
|
||||
0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,33,2,121,0,86,0,83,
|
||||
0,100,0,97,1,202,0,37,0,46,1,112,0,43,0,242,
|
||||
0,48,0,41,0,237,0,0,0,21,0,0,0,2,0,33,
|
||||
0,0,1,110,2,154,0,3,0,7,0,46,177,1,0,47,
|
||||
60,178,7,4,0,237,50,177,6,5,220,60,178,3,2,0,
|
||||
237,50,0,177,3,0,47,60,178,5,4,0,237,50,178,7,
|
||||
6,1,252,60,178,1,2,0,237,50,51,17,33,17,37,33,
|
||||
17,33,33,1,77,254,212,1,11,254,245,2,154,253,102,33,
|
||||
2,88,0,1,0,7,255,52,2,246,2,234,0,47,0,110,
|
||||
0,176,11,47,176,12,51,177,9,2,237,177,10,2,237,176,
|
||||
32,47,176,33,51,176,34,51,177,24,3,237,177,25,3,237,
|
||||
177,26,3,237,1,176,17,47,176,18,51,176,19,51,176,20,
|
||||
51,177,39,4,237,177,40,4,237,177,41,4,237,177,42,4,
|
||||
237,176,12,47,176,13,51,176,45,51,176,46,51,177,0,5,
|
||||
237,177,7,5,237,177,8,5,237,177,9,5,237,177,47,5,
|
||||
237,176,12,16,177,10,6,237,177,11,6,237,48,49,37,54,
|
||||
55,23,6,7,6,15,1,21,33,21,33,53,38,47,1,38,
|
||||
61,1,52,55,54,55,54,51,50,23,22,23,7,38,47,1,
|
||||
34,7,6,15,1,6,29,1,20,23,22,23,17,51,1,141,
|
||||
130,31,97,46,161,24,26,1,1,105,254,54,183,70,1,39,
|
||||
122,22,25,80,97,176,81,20,13,96,45,128,23,135,63,12,
|
||||
8,3,23,112,39,42,97,76,31,150,24,185,47,7,3,1,
|
||||
108,86,194,19,166,1,91,104,1,198,100,18,14,44,136,35,
|
||||
43,22,141,11,1,100,19,22,8,68,72,1,201,67,23,7,
|
||||
1,198,0,2,0,21,1,97,1,5,2,216,0,12,0,30,
|
||||
0,109,0,176,7,47,176,8,51,176,9,51,177,10,7,237,
|
||||
177,17,7,237,177,18,7,237,177,19,7,237,176,26,176,10,
|
||||
16,222,176,27,50,176,28,50,177,1,7,237,177,2,7,237,
|
||||
177,3,7,237,1,176,0,47,176,1,51,176,11,51,176,12,
|
||||
51,177,13,8,237,177,14,8,237,177,30,8,237,176,21,176,
|
||||
13,16,222,176,22,50,176,23,50,176,24,50,177,5,8,237,
|
||||
177,6,8,237,177,7,8,237,177,32,6,16,204,48,49,19,
|
||||
52,51,50,23,22,21,20,35,34,39,38,53,55,20,23,51,
|
||||
22,51,50,55,54,61,1,52,39,38,35,34,7,6,21,120,
|
||||
85,26,8,119,53,30,37,47,20,1,21,31,31,21,21,21,
|
||||
21,32,31,18,23,2,29,187,101,32,54,187,38,45,102,2,
|
||||
90,30,30,30,30,88,2,90,30,30,27,33,0,1,0,55,
|
||||
1,104,0,191,2,216,0,13,0,41,0,176,0,47,176,1,
|
||||
51,177,11,9,237,177,12,9,237,177,13,9,237,1,176,1,
|
||||
47,176,2,51,177,0,8,237,177,13,8,237,177,15,0,16,
|
||||
204,48,49,19,35,17,6,7,6,7,53,54,55,54,63,1,
|
||||
51,191,45,17,26,26,21,37,29,27,12,1,29,1,104,1,
|
||||
31,16,15,16,8,44,18,25,25,23,1,0,0,1,0,15,
|
||||
1,104,1,2,2,216,0,37,0,96,0,176,1,47,176,2,
|
||||
51,177,0,10,237,177,37,10,237,176,15,176,0,16,222,176,
|
||||
16,50,176,17,50,177,23,7,237,177,24,7,237,177,25,7,
|
||||
237,1,176,2,47,176,3,51,177,0,11,237,177,1,11,237,
|
||||
177,28,11,237,177,29,11,237,177,30,11,237,176,29,16,177,
|
||||
10,8,237,177,11,8,237,177,12,8,237,177,13,8,237,177,
|
||||
25,8,237,177,39,0,16,204,48,49,1,21,35,38,55,53,
|
||||
54,55,54,55,54,61,1,52,39,38,35,34,7,21,7,39,
|
||||
54,63,1,50,23,22,31,1,20,15,1,6,7,6,15,1,
|
||||
1,2,242,2,36,21,38,60,21,21,41,13,15,56,13,3,
|
||||
46,8,82,29,70,31,10,2,1,38,1,21,48,52,13,6,
|
||||
1,147,43,37,42,1,24,32,49,28,28,25,1,43,16,5,
|
||||
50,1,23,5,89,15,2,50,17,20,15,44,43,1,23,41,
|
||||
44,17,10,0,0,1,0,21,1,97,1,6,2,216,0,52,
|
||||
0,133,0,176,48,47,176,49,51,176,50,51,177,2,7,237,
|
||||
177,3,7,237,177,4,7,237,176,13,176,2,16,222,176,14,
|
||||
50,176,15,50,177,17,0,237,177,18,0,237,177,19,0,237,
|
||||
176,26,176,17,16,222,176,27,50,176,28,50,177,33,7,237,
|
||||
177,34,7,237,177,35,7,237,1,176,21,47,176,22,51,176,
|
||||
23,51,176,24,51,176,35,51,177,38,8,237,177,39,8,237,
|
||||
177,40,8,237,177,41,8,237,176,8,47,176,9,51,176,10,
|
||||
51,176,11,51,177,44,12,237,177,45,12,237,177,46,12,237,
|
||||
177,54,45,16,204,48,49,19,55,22,51,50,55,61,1,54,
|
||||
61,1,52,39,38,35,34,7,55,23,50,55,54,61,1,52,
|
||||
39,38,35,34,7,39,54,55,54,51,50,23,49,22,21,23,
|
||||
20,7,22,31,1,20,7,6,35,34,39,38,22,44,15,57,
|
||||
47,21,8,40,15,17,13,19,5,7,55,16,4,34,12,14,
|
||||
56,10,45,13,63,16,18,59,31,17,1,51,59,8,2,57,
|
||||
30,37,71,32,11,1,201,6,72,41,1,1,15,17,1,47,
|
||||
18,6,4,39,1,38,11,12,1,38,14,5,66,8,73,17,
|
||||
5,42,23,29,1,51,24,13,60,17,65,32,17,57,20,0,
|
||||
0,2,0,6,1,104,1,4,2,215,0,10,0,13,0,114,
|
||||
0,176,1,47,176,2,51,176,8,51,176,9,51,177,3,13,
|
||||
237,177,6,13,237,177,7,13,237,177,11,13,237,177,13,13,
|
||||
237,177,4,6,16,204,177,5,6,16,204,177,10,1,16,204,
|
||||
177,0,1,16,204,1,176,0,47,176,1,51,176,11,51,176,
|
||||
12,51,177,5,8,237,177,6,8,237,177,9,8,237,177,10,
|
||||
8,237,177,4,6,16,204,177,8,6,16,204,177,7,6,16,
|
||||
204,177,3,1,16,204,177,2,1,16,204,177,15,7,16,204,
|
||||
48,49,19,53,35,53,55,51,21,51,21,35,21,39,53,7,
|
||||
166,160,168,36,50,50,44,115,1,104,88,41,237,237,41,88,
|
||||
129,165,165,0,0,1,0,21,1,97,1,9,2,210,0,36,
|
||||
0,102,0,176,32,47,176,33,51,176,34,51,177,3,7,237,
|
||||
177,4,7,237,177,5,7,237,176,12,176,3,16,222,176,13,
|
||||
50,176,14,50,177,22,13,237,177,23,13,237,177,24,13,237,
|
||||
176,19,176,22,16,222,176,20,50,177,17,10,237,177,18,10,
|
||||
237,1,176,7,47,176,8,51,176,9,51,176,10,51,176,24,
|
||||
51,177,27,12,237,177,28,12,237,177,29,12,237,177,30,12,
|
||||
237,177,38,29,16,204,48,49,19,55,22,31,1,50,55,54,
|
||||
61,1,52,39,38,35,34,7,39,55,51,21,35,7,54,51,
|
||||
50,23,21,22,29,1,20,7,6,35,34,39,38,21,47,9,
|
||||
47,15,51,19,7,46,15,17,44,22,43,36,182,146,20,33,
|
||||
36,66,32,16,57,30,38,76,30,9,1,200,4,58,10,1,
|
||||
49,18,21,1,59,19,5,35,5,189,44,98,23,55,1,27,
|
||||
35,1,75,36,19,60,19,0,0,2,0,19,1,97,1,6,
|
||||
2,216,0,29,0,47,0,136,0,176,17,47,176,18,51,176,
|
||||
19,51,177,33,7,237,177,34,7,237,177,35,7,237,176,42,
|
||||
176,33,16,222,176,43,50,176,44,50,176,45,50,177,8,13,
|
||||
237,177,9,13,237,177,10,13,237,176,2,176,8,16,222,176,
|
||||
3,50,176,4,50,177,25,7,237,177,26,7,237,177,27,7,
|
||||
237,177,28,7,237,1,176,21,47,176,22,51,176,23,51,176,
|
||||
24,51,177,6,10,237,177,7,10,237,176,10,47,176,37,51,
|
||||
176,38,51,176,39,51,176,40,51,177,12,8,237,177,13,8,
|
||||
237,177,14,8,237,177,15,8,237,177,49,14,16,204,48,49,
|
||||
1,7,38,35,34,7,6,21,54,51,50,23,22,29,1,20,
|
||||
7,6,35,34,39,38,39,53,52,55,54,51,50,23,7,20,
|
||||
23,22,51,50,55,54,61,1,52,39,38,39,35,34,7,6,
|
||||
0,255,45,13,49,48,23,13,32,57,64,30,14,52,27,36,
|
||||
56,35,35,1,117,7,8,73,24,177,36,18,21,46,17,6,
|
||||
41,11,14,5,47,19,7,2,125,4,58,57,30,55,49,57,
|
||||
28,33,1,73,34,18,41,41,94,2,184,11,1,63,186,52,
|
||||
25,11,49,16,19,1,56,19,6,1,44,16,0,1,0,24,
|
||||
1,104,1,6,2,210,0,16,0,43,0,176,0,47,176,16,
|
||||
51,177,1,10,237,177,2,10,237,176,9,47,176,10,47,1,
|
||||
176,0,47,176,1,51,177,2,14,237,177,3,14,237,177,18,
|
||||
2,16,204,48,49,19,53,51,21,6,7,6,7,6,7,35,
|
||||
54,55,52,55,54,55,24,238,71,42,6,4,14,3,46,5,
|
||||
86,1,17,19,2,166,44,35,75,120,16,15,46,55,140,129,
|
||||
2,1,25,21,0,3,0,20,1,97,1,7,2,216,0,32,
|
||||
0,51,0,69,0,207,0,176,24,47,176,25,51,176,26,51,
|
||||
177,55,7,237,177,56,7,237,177,57,7,237,176,17,176,55,
|
||||
16,222,176,31,50,176,64,50,176,65,50,176,66,50,177,36,
|
||||
7,237,177,37,7,237,177,38,7,237,176,3,176,36,16,222,
|
||||
176,45,50,176,46,50,176,47,50,177,5,7,237,177,6,7,
|
||||
237,177,7,7,237,1,176,28,47,176,29,51,176,30,51,176,
|
||||
31,51,177,52,8,237,177,53,8,237,177,68,8,237,177,69,
|
||||
8,237,176,1,47,176,2,51,176,3,51,176,27,51,177,33,
|
||||
8,237,177,34,8,237,177,50,8,237,177,51,8,237,176,40,
|
||||
47,176,41,51,176,42,51,176,43,51,177,12,8,237,177,13,
|
||||
8,237,177,14,8,237,177,15,8,237,176,59,47,176,60,51,
|
||||
176,61,51,176,62,51,177,17,8,237,177,18,8,237,177,19,
|
||||
8,237,177,20,8,237,177,21,8,237,177,22,8,237,177,71,
|
||||
21,16,204,48,49,19,38,53,52,55,54,51,50,31,1,21,
|
||||
23,22,29,1,20,7,22,23,20,29,1,20,7,6,35,34,
|
||||
39,38,61,1,52,55,39,20,23,22,51,50,55,54,61,1,
|
||||
52,39,38,35,34,15,1,6,21,7,20,23,22,51,50,55,
|
||||
54,61,1,52,39,38,35,34,7,6,21,90,54,54,23,28,
|
||||
63,29,1,1,12,54,67,2,58,28,34,72,33,16,67,6,
|
||||
37,11,12,40,14,5,35,12,13,38,16,1,4,15,40,16,
|
||||
19,48,19,7,41,16,19,47,19,7,2,47,20,55,59,25,
|
||||
10,46,1,1,1,21,25,1,53,20,22,69,1,1,1,67,
|
||||
30,14,52,26,33,1,73,19,77,42,13,4,34,10,11,1,
|
||||
39,15,5,32,1,11,11,170,48,19,8,40,15,17,1,48,
|
||||
20,7,40,15,17,0,0,2,0,21,1,97,1,7,2,216,
|
||||
0,35,0,58,0,133,0,176,32,47,176,33,51,176,34,51,
|
||||
177,2,7,237,177,3,7,237,177,4,7,237,176,11,176,2,
|
||||
16,222,176,12,50,176,13,50,177,7,13,237,177,8,13,237,
|
||||
177,53,13,237,177,54,13,237,177,55,13,237,176,41,176,8,
|
||||
16,222,176,42,50,176,43,50,177,21,7,237,177,22,7,237,
|
||||
177,23,7,237,1,176,16,47,176,17,51,176,18,51,176,19,
|
||||
51,177,13,8,237,177,49,8,237,177,50,8,237,177,51,8,
|
||||
237,176,6,47,176,7,51,176,8,51,176,9,51,177,28,10,
|
||||
237,177,29,10,237,177,30,10,237,48,49,19,55,22,51,50,
|
||||
55,54,53,55,39,6,15,1,34,39,53,38,61,1,52,55,
|
||||
54,51,50,31,1,21,23,22,21,20,7,6,35,34,39,55,
|
||||
52,39,34,49,38,35,34,15,1,21,7,21,6,21,20,23,
|
||||
22,51,50,55,54,53,28,43,11,50,61,19,5,1,1,27,
|
||||
52,8,65,30,14,54,27,34,72,34,1,4,15,60,30,41,
|
||||
76,22,179,37,1,14,18,45,20,1,1,7,39,15,19,52,
|
||||
15,4,1,189,4,58,79,24,28,2,8,43,4,1,58,1,
|
||||
27,33,1,73,34,17,64,1,1,8,36,67,132,43,22,67,
|
||||
185,54,22,9,45,1,1,1,1,18,21,50,21,8,52,14,
|
||||
15,0,0,1,0,0,255,243,1,2,2,234,0,3,0,20,
|
||||
176,0,47,176,1,47,176,2,47,176,3,47,1,177,5,2,
|
||||
47,204,48,49,21,19,51,3,212,46,214,12,2,246,253,10,
|
||||
0,2,0,21,255,249,1,5,1,112,0,12,0,31,0,113,
|
||||
0,176,7,47,176,8,51,176,9,51,177,10,7,237,177,17,
|
||||
7,237,177,18,7,237,177,19,7,237,176,26,176,10,16,222,
|
||||
176,27,50,176,28,50,177,1,7,237,177,2,7,237,177,3,
|
||||
7,237,1,176,0,47,176,1,51,176,11,51,176,12,51,177,
|
||||
13,8,237,177,14,8,237,177,30,8,237,177,31,8,237,176,
|
||||
21,176,13,16,222,176,22,50,176,23,50,176,24,50,177,5,
|
||||
8,237,177,6,8,237,177,7,8,237,177,33,6,16,204,48,
|
||||
49,55,52,51,50,23,22,21,20,35,34,39,38,53,55,20,
|
||||
23,51,22,51,50,55,54,61,1,52,39,38,35,34,7,6,
|
||||
21,21,120,85,26,8,119,53,30,37,47,20,1,21,31,31,
|
||||
21,21,21,21,32,31,18,23,181,187,101,32,54,187,38,45,
|
||||
102,2,90,30,30,30,30,88,2,90,30,30,27,33,89,0,
|
||||
0,1,0,55,0,0,0,191,1,112,0,13,0,42,0,177,
|
||||
0,15,63,176,1,51,177,11,9,237,177,12,9,237,177,13,
|
||||
9,237,1,176,1,47,176,2,51,177,0,8,237,177,13,8,
|
||||
237,177,15,0,16,204,48,49,51,35,17,6,7,6,7,53,
|
||||
54,55,54,63,1,51,191,45,17,26,26,21,37,29,27,12,
|
||||
1,29,1,31,16,15,16,8,44,18,25,25,23,1,0,1,
|
||||
0,15,0,0,1,2,1,112,0,38,0,101,0,177,1,15,
|
||||
63,176,2,51,177,0,10,237,177,38,10,237,176,14,176,0,
|
||||
16,222,176,15,50,176,16,50,177,23,7,237,177,24,7,237,
|
||||
177,25,7,237,1,176,2,47,176,3,51,177,0,11,237,177,
|
||||
1,11,237,177,28,11,237,177,29,11,237,177,30,11,237,177,
|
||||
31,11,237,176,28,16,177,9,8,237,177,10,8,237,177,11,
|
||||
8,237,177,12,8,237,177,25,8,237,177,40,0,16,204,48,
|
||||
49,37,21,35,38,55,54,55,54,55,54,61,1,52,39,38,
|
||||
35,34,7,29,1,7,39,54,63,1,50,23,21,22,29,1,
|
||||
20,15,1,6,7,6,15,1,1,2,242,2,36,21,38,60,
|
||||
21,21,41,13,15,56,13,3,46,8,82,29,70,31,13,38,
|
||||
1,21,48,52,13,6,43,43,38,42,24,32,49,28,28,25,
|
||||
1,43,16,5,50,1,1,22,5,89,15,2,50,1,22,28,
|
||||
1,44,43,1,23,41,44,17,10,0,0,1,0,21,255,249,
|
||||
1,6,1,112,0,51,0,133,0,176,47,47,176,48,51,176,
|
||||
49,51,177,2,7,237,177,3,7,237,177,4,7,237,176,11,
|
||||
176,2,16,222,176,12,50,176,13,50,177,15,0,237,177,16,
|
||||
0,237,177,17,0,237,176,24,176,15,16,222,176,25,50,176,
|
||||
26,50,177,31,7,237,177,32,7,237,177,33,7,237,1,176,
|
||||
19,47,176,20,51,176,21,51,176,22,51,176,33,51,177,37,
|
||||
8,237,177,38,8,237,177,39,8,237,177,40,8,237,176,6,
|
||||
47,176,7,51,176,8,51,176,9,51,177,43,12,237,177,44,
|
||||
12,237,177,45,12,237,177,53,44,16,204,48,49,63,1,22,
|
||||
51,50,55,54,61,1,52,39,38,35,34,7,55,23,50,55,
|
||||
54,61,1,52,39,38,35,34,7,39,54,55,54,51,50,31,
|
||||
1,49,22,21,23,20,7,22,31,1,20,7,6,39,34,39,
|
||||
38,22,44,15,57,47,21,8,40,15,17,13,19,5,7,55,
|
||||
16,4,34,12,14,56,10,45,13,63,16,18,61,30,1,15,
|
||||
1,51,59,8,2,57,30,37,71,32,11,97,6,72,41,16,
|
||||
18,1,47,18,6,4,39,1,38,11,12,1,38,14,5,66,
|
||||
8,73,17,5,43,1,22,28,1,51,24,13,60,17,65,32,
|
||||
18,1,57,20,0,2,0,6,0,0,1,4,1,111,0,10,
|
||||
0,13,0,111,0,177,0,15,63,176,10,51,176,1,222,176,
|
||||
2,50,176,8,50,176,9,50,177,3,13,237,177,6,13,237,
|
||||
177,7,13,237,177,11,13,237,177,13,13,237,177,4,6,16,
|
||||
204,177,5,6,16,204,1,176,0,47,176,1,51,176,11,51,
|
||||
176,12,51,177,5,8,237,177,6,8,237,177,9,8,237,177,
|
||||
10,8,237,177,4,6,16,204,177,8,6,16,204,177,7,6,
|
||||
16,204,177,3,1,16,204,177,2,1,16,204,177,15,7,16,
|
||||
204,48,49,51,53,35,53,55,51,21,51,21,35,21,39,53,
|
||||
7,166,160,168,36,50,50,44,115,88,41,237,237,41,88,129,
|
||||
165,165,0,1,0,21,255,249,1,9,1,106,0,36,0,106,
|
||||
0,176,32,47,176,33,51,176,34,51,177,3,7,237,177,4,
|
||||
7,237,177,5,7,237,177,6,7,237,176,13,176,3,16,222,
|
||||
176,14,50,176,15,50,177,23,13,237,177,24,13,237,177,25,
|
||||
13,237,176,20,176,23,16,222,176,21,50,177,18,10,237,177,
|
||||
19,10,237,1,176,8,47,176,9,51,176,10,51,176,11,51,
|
||||
176,25,51,177,27,12,237,177,28,12,237,177,29,12,237,177,
|
||||
30,12,237,177,38,29,16,204,48,49,63,1,22,23,22,51,
|
||||
50,55,54,61,1,52,39,38,35,34,7,39,55,51,21,35,
|
||||
7,54,51,50,23,22,29,1,20,7,6,35,34,39,38,21,
|
||||
47,9,47,7,8,51,19,7,46,15,17,44,22,43,36,182,
|
||||
146,20,33,36,66,32,16,57,30,38,76,30,9,96,4,58,
|
||||
10,1,49,18,21,1,59,19,5,35,5,189,44,98,23,55,
|
||||
28,35,1,75,36,19,60,19,0,2,0,12,255,249,0,255,
|
||||
1,112,0,31,0,49,0,129,0,176,17,47,176,18,51,176,
|
||||
19,51,177,35,7,237,177,36,7,237,177,37,7,237,176,44,
|
||||
176,35,16,222,176,45,50,176,46,50,177,8,13,237,177,9,
|
||||
13,237,177,10,13,237,176,2,176,8,16,222,176,3,50,176,
|
||||
4,50,177,25,7,237,177,26,7,237,177,27,7,237,1,176,
|
||||
21,47,176,22,51,176,23,51,176,24,51,177,6,10,237,177,
|
||||
7,10,237,176,10,47,176,39,51,176,40,51,176,41,51,176,
|
||||
42,51,177,12,8,237,177,13,8,237,177,14,8,237,177,15,
|
||||
8,237,177,51,14,16,204,48,49,19,7,38,35,34,7,6,
|
||||
21,54,51,50,23,22,29,1,20,7,6,35,34,39,38,39,
|
||||
53,52,63,1,50,23,21,22,23,7,20,23,22,51,50,55,
|
||||
54,61,1,52,39,38,35,34,7,6,21,248,45,13,49,48,
|
||||
23,13,32,57,64,30,14,52,27,35,57,35,35,1,117,15,
|
||||
73,24,5,2,184,36,18,21,46,17,6,41,13,17,47,19,
|
||||
7,1,21,4,58,57,30,55,49,57,28,33,1,73,34,18,
|
||||
41,41,94,2,184,11,1,63,1,12,14,159,52,25,11,49,
|
||||
16,19,1,56,19,7,44,16,18,0,0,1,0,24,0,0,
|
||||
1,6,1,106,0,14,0,44,0,177,9,15,63,176,10,51,
|
||||
176,0,222,176,14,50,177,1,10,237,177,2,10,237,1,176,
|
||||
0,47,176,1,51,177,2,14,237,177,3,14,237,177,16,2,
|
||||
16,204,48,49,19,53,51,21,6,7,6,7,6,7,35,54,
|
||||
55,54,55,24,238,71,42,6,4,14,3,46,5,86,18,19,
|
||||
1,62,44,35,75,120,16,15,46,55,140,129,27,22,0,3,
|
||||
0,20,255,249,1,7,1,112,0,29,0,47,0,65,0,203,
|
||||
0,176,20,47,176,21,51,176,22,51,177,51,7,237,177,52,
|
||||
7,237,177,53,7,237,176,14,176,51,16,222,176,27,50,176,
|
||||
60,50,176,61,50,176,62,50,177,33,7,237,177,34,7,237,
|
||||
177,35,7,237,176,3,176,33,16,222,176,42,50,176,43,50,
|
||||
176,44,50,177,5,7,237,177,6,7,237,177,7,7,237,1,
|
||||
176,24,47,176,25,51,176,26,51,176,27,51,177,48,8,237,
|
||||
177,49,8,237,177,64,8,237,177,65,8,237,176,1,47,176,
|
||||
2,51,176,3,51,176,23,51,177,30,8,237,177,31,8,237,
|
||||
177,46,8,237,177,47,8,237,176,37,47,176,38,51,176,39,
|
||||
51,176,40,51,177,9,8,237,177,10,8,237,177,11,8,237,
|
||||
177,12,8,237,176,55,47,176,56,51,176,57,51,176,58,51,
|
||||
177,14,8,237,177,15,8,237,177,16,8,237,177,17,8,237,
|
||||
177,18,8,237,177,67,17,16,204,48,49,55,38,53,52,55,
|
||||
54,51,50,23,22,29,1,20,7,22,23,20,49,20,7,6,
|
||||
35,34,39,38,61,1,52,55,50,39,20,23,22,51,50,55,
|
||||
54,61,1,52,39,38,35,34,7,6,21,7,20,23,22,51,
|
||||
50,55,54,61,1,52,39,38,35,34,7,6,21,90,54,54,
|
||||
23,28,63,29,14,54,67,2,58,28,34,72,33,16,65,2,
|
||||
6,37,11,12,40,14,5,35,12,13,38,16,5,15,40,16,
|
||||
19,48,19,7,41,16,19,47,19,7,199,20,55,59,25,10,
|
||||
46,22,27,1,53,20,22,69,3,67,30,14,52,26,33,1,
|
||||
72,20,77,42,13,4,34,10,11,1,39,15,5,32,11,12,
|
||||
170,48,19,8,40,15,17,1,48,20,7,40,15,17,0,2,
|
||||
0,21,255,249,1,7,1,112,0,33,0,52,0,133,0,176,
|
||||
29,47,176,30,51,176,31,51,177,2,7,237,177,3,7,237,
|
||||
177,4,7,237,176,11,176,2,16,222,176,12,50,176,13,50,
|
||||
177,7,13,237,177,8,13,237,177,47,13,237,177,48,13,237,
|
||||
177,49,13,237,176,39,176,8,16,222,176,40,50,176,41,50,
|
||||
177,20,7,237,177,21,7,237,177,22,7,237,1,176,15,47,
|
||||
176,16,51,176,17,51,176,18,51,177,13,8,237,177,43,8,
|
||||
237,177,44,8,237,177,45,8,237,176,6,47,176,7,51,176,
|
||||
8,51,176,9,51,177,25,10,237,177,26,10,237,177,27,10,
|
||||
237,48,49,63,1,22,51,50,55,54,53,55,39,6,15,1,
|
||||
34,39,38,61,1,52,55,54,51,50,31,1,22,21,20,7,
|
||||
6,35,34,39,38,55,52,39,34,49,38,35,34,7,6,21,
|
||||
20,23,22,51,50,55,54,53,28,43,11,50,40,22,23,1,
|
||||
1,27,52,8,65,30,14,54,27,34,72,34,5,15,60,30,
|
||||
41,76,22,3,182,37,1,14,18,46,20,8,39,15,19,52,
|
||||
15,4,85,4,58,35,36,60,2,8,43,4,1,58,27,34,
|
||||
1,73,34,17,64,10,36,67,132,43,22,67,11,174,54,22,
|
||||
9,46,20,22,50,21,8,52,14,15,0,0,0,1,0,0,
|
||||
0,0,0,0,233,217,10,104,95,15,60,245,0,19,3,232,
|
||||
0,0,0,0,184,207,153,237,0,0,0,0,184,207,153,237,
|
||||
0,0,255,52,2,246,2,234,0,0,0,8,0,2,0,0,
|
||||
0,0,0,0,0,1,0,0,3,32,255,56,0,90,2,142,
|
||||
0,0,255,152,2,246,0,1,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,25,1,176,0,33,0,0,0,0,
|
||||
1,77,0,0,2,142,0,7,1,15,0,21,0,235,0,55,
|
||||
1,31,0,15,1,23,0,21,1,23,0,6,1,30,0,21,
|
||||
1,28,0,19,1,25,0,24,1,28,0,20,1,23,0,21,
|
||||
1,27,0,0,1,15,0,21,0,235,0,55,1,31,0,15,
|
||||
1,25,0,21,1,22,0,6,1,31,0,21,1,21,0,12,
|
||||
1,25,0,24,1,28,0,20,1,31,0,21,0,0,0,1,
|
||||
0,0,0,158,0,1,0,24,0,96,0,4,255,208,0,4,
|
||||
0,4,0,0,0,4,0,14,255,122,0,5,0,5,0,0,
|
||||
0,5,0,14,255,152,0,6,0,6,0,0,0,6,0,14,
|
||||
255,150,0,7,0,14,255,122,0,8,0,14,255,122,0,9,
|
||||
0,14,255,115,0,10,0,14,255,115,0,11,0,14,255,92,
|
||||
0,12,0,14,255,115,0,13,0,14,255,115,0,14,0,14,
|
||||
255,211,0,14,0,15,255,107,0,14,0,16,255,85,0,14,
|
||||
0,17,255,107,0,14,0,18,255,115,0,14,0,19,255,92,
|
||||
0,14,0,20,255,100,0,14,0,21,255,107,0,14,0,22,
|
||||
255,130,0,14,0,23,255,100,0,14,0,24,255,107,0,0,
|
||||
0,0,0,43,0,43,0,43,0,171,1,16,1,64,1,172,
|
||||
2,58,2,140,2,246,3,128,3,180,4,125,5,19,5,42,
|
||||
5,146,5,193,6,47,6,188,7,11,7,118,7,255,8,49,
|
||||
8,241,9,127,0,1,0,0,0,25,0,70,0,3,0,0,
|
||||
0,0,0,2,0,0,0,1,0,1,0,0,0,64,0,207,
|
||||
0,0,0,0,0,0,0,26,1,62,0,1,0,0,0,0,
|
||||
0,0,0,65,0,0,0,1,0,0,0,0,0,1,0,9,
|
||||
0,66,0,1,0,0,0,0,0,2,0,7,0,76,0,1,
|
||||
0,0,0,0,0,3,0,34,0,84,0,1,0,0,0,0,
|
||||
0,4,0,9,0,119,0,1,0,0,0,0,0,5,0,7,
|
||||
0,129,0,1,0,0,0,0,0,6,0,9,0,137,0,0,
|
||||
0,3,0,0,0,0,0,130,0,147,0,0,0,3,0,0,
|
||||
0,1,0,18,1,23,0,0,0,3,0,0,0,2,0,14,
|
||||
1,43,0,0,0,3,0,0,0,3,0,68,1,59,0,0,
|
||||
0,3,0,0,0,4,0,18,1,129,0,0,0,3,0,0,
|
||||
0,5,0,14,1,149,0,0,0,3,0,0,0,6,0,18,
|
||||
1,165,0,3,0,1,4,9,0,0,0,130,0,147,0,3,
|
||||
0,1,4,9,0,1,0,18,1,23,0,3,0,1,4,9,
|
||||
0,2,0,14,1,43,0,3,0,1,4,9,0,3,0,68,
|
||||
1,59,0,3,0,1,4,9,0,4,0,18,1,129,0,3,
|
||||
0,1,4,9,0,5,0,14,1,149,0,3,0,1,4,9,
|
||||
0,6,0,18,1,165,0,3,0,1,0,0,0,4,0,34,
|
||||
1,185,0,3,0,1,0,0,0,8,0,44,1,221,0,3,
|
||||
0,1,0,0,0,11,0,46,2,11,0,3,0,1,0,0,
|
||||
0,13,0,6,2,59,0,3,0,1,0,0,0,14,0,36,
|
||||
2,67,67,114,101,97,116,101,100,32,98,121,32,65,108,108,
|
||||
101,110,32,66,97,114,110,101,116,116,32,119,105,116,104,32,
|
||||
80,102,97,69,100,105,116,32,49,46,48,32,40,104,116,116,
|
||||
112,58,47,47,112,102,97,101,100,105,116,46,115,102,46,110,
|
||||
101,116,41,0,108,67,83,121,109,98,111,108,115,0,82,101,
|
||||
103,117,108,97,114,0,80,102,97,69,100,105,116,32,49,46,
|
||||
48,32,58,32,108,67,83,121,109,98,111,108,115,32,58,32,
|
||||
50,45,51,45,50,48,55,50,0,108,67,83,121,109,98,111,
|
||||
108,115,0,48,48,49,46,48,48,48,0,108,67,83,121,109,
|
||||
98,111,108,115,0,0,67,0,114,0,101,0,97,0,116,0,
|
||||
101,0,100,0,32,0,98,0,121,0,32,0,65,0,108,0,
|
||||
108,0,101,0,110,0,32,0,66,0,97,0,114,0,110,0,
|
||||
101,0,116,0,116,0,32,0,119,0,105,0,116,0,104,0,
|
||||
32,0,80,0,102,0,97,0,69,0,100,0,105,0,116,0,
|
||||
32,0,49,0,46,0,48,0,32,0,40,0,104,0,116,0,
|
||||
116,0,112,0,58,0,47,0,47,0,112,0,102,0,97,0,
|
||||
101,0,100,0,105,0,116,0,46,0,115,0,102,0,46,0,
|
||||
110,0,101,0,116,0,41,0,0,0,108,0,67,0,83,0,
|
||||
121,0,109,0,98,0,111,0,108,0,115,0,0,0,82,0,
|
||||
101,0,103,0,117,0,108,0,97,0,114,0,0,0,80,0,
|
||||
102,0,97,0,69,0,100,0,105,0,116,0,32,0,49,0,
|
||||
46,0,48,0,32,0,58,0,32,0,108,0,67,0,83,0,
|
||||
121,0,109,0,98,0,111,0,108,0,115,0,32,0,58,0,
|
||||
32,0,50,0,45,0,51,0,45,0,50,0,48,0,55,0,
|
||||
50,0,0,0,108,0,67,0,83,0,121,0,109,0,98,0,
|
||||
111,0,108,0,115,0,0,0,48,0,48,0,49,0,46,0,
|
||||
48,0,48,0,48,0,0,0,108,0,67,0,83,0,121,0,
|
||||
109,0,98,0,111,0,108,0,115,0,0,0,108,0,105,0,
|
||||
103,0,110,0,117,0,109,0,67,0,65,0,68,0,32,0,
|
||||
83,0,121,0,109,0,98,0,111,0,108,0,115,0,0,0,
|
||||
108,0,105,0,103,0,110,0,117,0,109,0,32,0,67,0,
|
||||
111,0,109,0,112,0,117,0,116,0,105,0,110,0,103,0,
|
||||
44,0,32,0,73,0,110,0,99,0,46,0,0,0,119,0,
|
||||
119,0,119,0,46,0,108,0,105,0,103,0,110,0,117,0,
|
||||
109,0,99,0,111,0,109,0,112,0,117,0,116,0,105,0,
|
||||
110,0,103,0,46,0,99,0,111,0,109,0,0,0,71,0,
|
||||
80,0,76,0,0,0,104,0,116,0,116,0,112,0,58,0,
|
||||
47,0,47,0,119,0,119,0,119,0,46,0,103,0,110,0,
|
||||
117,0,46,0,111,0,114,0,103,0,0,0,0,2,0,0,
|
||||
0,0,0,0,255,156,0,50,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,25,0,0,
|
||||
0,1,0,2,1,2,1,3,1,4,1,5,1,6,1,7,
|
||||
1,8,1,9,1,10,1,11,1,12,1,13,1,14,1,15,
|
||||
1,16,1,17,1,18,1,19,1,20,1,21,1,22,1,23,
|
||||
7,117,110,105,50,49,48,52,7,117,110,105,69,48,48,48,
|
||||
7,117,110,105,69,48,48,49,7,117,110,105,69,48,48,50,
|
||||
7,117,110,105,69,48,48,51,7,117,110,105,69,48,48,52,
|
||||
7,117,110,105,69,48,48,53,7,117,110,105,69,48,48,54,
|
||||
7,117,110,105,69,48,48,55,7,117,110,105,69,48,48,56,
|
||||
7,117,110,105,69,48,48,57,7,117,110,105,69,48,48,65,
|
||||
7,117,110,105,69,48,49,48,7,117,110,105,69,48,49,49,
|
||||
7,117,110,105,69,48,49,50,7,117,110,105,69,48,49,51,
|
||||
7,117,110,105,69,48,49,52,7,117,110,105,69,48,49,53,
|
||||
7,117,110,105,69,48,49,54,7,117,110,105,69,48,49,55,
|
||||
7,117,110,105,69,48,49,56,7,117,110,105,69,48,49,57,
|
||||
};
|
||||
const int lCSymbols_ttf_size = sizeof( lCSymbols_ttf );
|
||||
|
After Width: | Height: | Size: 464 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 138 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 118 KiB |
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* demo.cpp: Demo of the OGLFT library
|
||||
* Copyright (C) 2002 lignum Computing, Inc. <oglft@lignumcomputing.com>
|
||||
* $Id$
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <GL/glut.h>
|
||||
|
||||
#include <OGLFT.h>
|
||||
|
||||
static const char* USAGE = " fontfile";
|
||||
|
||||
static const char* commands = "a/A: char rotate X, s/S: char rotate Y, d/D: char rotate Z, f/F: string rotate, r: reset all";
|
||||
static const char* text = "The quick brown fox jumps over a lazy dog.";
|
||||
static const float point_size = 16;
|
||||
|
||||
static OGLFT::Monochrome* commands_face;
|
||||
static OGLFT::Monochrome* monochrome_face;
|
||||
static OGLFT::Grayscale* grayscale_face;
|
||||
static OGLFT::Translucent* translucent_face;
|
||||
static OGLFT::Outline* outline_face;
|
||||
static OGLFT::Filled* filled_face;
|
||||
#ifndef OGLFT_NO_SOLID
|
||||
static OGLFT::Solid* solid_face;
|
||||
#else
|
||||
static OGLFT::Monochrome* solid_face;
|
||||
#endif
|
||||
static OGLFT::MonochromeTexture* monochrome_texture_face;
|
||||
static OGLFT::GrayscaleTexture* grayscale_texture_face;
|
||||
static OGLFT::TranslucentTexture* translucent_texture_face;
|
||||
|
||||
|
||||
static float dy;
|
||||
static int viewport_width;
|
||||
static int viewport_height;
|
||||
|
||||
static void init ( int /*argc*/, char* argv[] )
|
||||
{
|
||||
std::cout << glGetString( GL_VENDOR ) << " " << glGetString( GL_RENDERER ) << " "
|
||||
<< glGetString( GL_VERSION ) << std::endl;
|
||||
|
||||
commands_face = new OGLFT::Monochrome( argv[1], point_size / 2. );
|
||||
commands_face->setHorizontalJustification( OGLFT::Face::CENTER );
|
||||
|
||||
monochrome_face = new OGLFT::Monochrome( argv[1], point_size );
|
||||
monochrome_face->setHorizontalJustification( OGLFT::Face::CENTER );
|
||||
monochrome_face->setForegroundColor( 1., 0., 0., 1. );
|
||||
|
||||
if ( !monochrome_face->isValid() ) {
|
||||
std::cerr << "failed to open face. exiting." << std::endl;
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
grayscale_face = new OGLFT::Grayscale( argv[1], point_size );
|
||||
grayscale_face->setHorizontalJustification( OGLFT::Face::CENTER );
|
||||
grayscale_face->setForegroundColor( 0., 0., .5, 1. );
|
||||
grayscale_face->setBackgroundColor( 0., 1., 1., 1. );
|
||||
|
||||
translucent_face = new OGLFT::Translucent( argv[1], point_size );
|
||||
translucent_face->setHorizontalJustification( OGLFT::Face::CENTER );
|
||||
translucent_face->setForegroundColor( 0., .5, 0., 1. );
|
||||
|
||||
outline_face = new OGLFT::Outline( argv[1], point_size );
|
||||
outline_face->setHorizontalJustification( OGLFT::Face::CENTER );
|
||||
outline_face->setForegroundColor( 1., 1., 0., 1. );
|
||||
|
||||
filled_face = new OGLFT::Filled( argv[1], point_size );
|
||||
filled_face->setHorizontalJustification( OGLFT::Face::CENTER );
|
||||
filled_face->setForegroundColor( .5, 0., 1., 1. );
|
||||
|
||||
#ifndef OGLFT_NO_SOLID
|
||||
solid_face = new OGLFT::Solid( argv[1], point_size );
|
||||
solid_face->setDepth( 10. );
|
||||
solid_face->setCharacterRotationX( 25. );
|
||||
solid_face->setCharacterRotationY( 25. );
|
||||
solid_face->setTessellationSteps( 3 );
|
||||
#else
|
||||
solid_face = new OGLFT::Monochrome( argv[1], point_size );
|
||||
#endif
|
||||
solid_face->setHorizontalJustification( OGLFT::Face::CENTER );
|
||||
solid_face->setForegroundColor( 1., .5, 0., 1. );
|
||||
|
||||
monochrome_texture_face = new OGLFT::MonochromeTexture( argv[1], point_size );
|
||||
monochrome_texture_face->setHorizontalJustification( OGLFT::Face::CENTER );
|
||||
monochrome_texture_face->setForegroundColor( 0., .5, .75, 1. );
|
||||
|
||||
grayscale_texture_face = new OGLFT::GrayscaleTexture( argv[1], point_size );
|
||||
grayscale_texture_face->setHorizontalJustification( OGLFT::Face::CENTER );
|
||||
grayscale_texture_face->setForegroundColor( 0.9, .65, .9, 1. );
|
||||
grayscale_texture_face->setBackgroundColor( 0.5, .5, .75, 0.3 );
|
||||
|
||||
translucent_texture_face = new OGLFT::TranslucentTexture( argv[1], point_size );
|
||||
translucent_texture_face->setHorizontalJustification( OGLFT::Face::CENTER );
|
||||
translucent_texture_face->setForegroundColor( 0.75, 1., .75, 1. );
|
||||
|
||||
// Set various general parameters which don't affect performance (yet).
|
||||
glClearColor( .75, .75, .75, 1. );
|
||||
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
|
||||
#if defined(GL_RASTER_POSITION_UNCLIPPED_IBM)
|
||||
glEnable( GL_RASTER_POSITION_UNCLIPPED_IBM );
|
||||
#endif
|
||||
glEnable( GL_LIGHT0 );
|
||||
glDisable( GL_DITHER );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
|
||||
}
|
||||
|
||||
static void reshape ( int width, int height )
|
||||
{
|
||||
viewport_width = width;
|
||||
viewport_height = height;
|
||||
|
||||
glViewport( 0, 0, viewport_width, viewport_height );
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadIdentity();
|
||||
glOrtho( 0, viewport_width, 0, viewport_height, -100, 100 );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
|
||||
dy = viewport_height / ( 9 + 1 );
|
||||
}
|
||||
|
||||
static void reset ( void )
|
||||
{
|
||||
monochrome_face->setCharacterRotationZ( 0 );
|
||||
monochrome_face->setStringRotation( 0 );
|
||||
|
||||
grayscale_face->setCharacterRotationZ( 0 );
|
||||
grayscale_face->setStringRotation( 0 );
|
||||
|
||||
translucent_face->setCharacterRotationZ( 0 );
|
||||
translucent_face->setStringRotation( 0 );
|
||||
|
||||
outline_face->setCharacterRotationX( 0 );
|
||||
outline_face->setCharacterRotationY( 0 );
|
||||
outline_face->setCharacterRotationZ( 0 );
|
||||
outline_face->setStringRotation( 0 );
|
||||
|
||||
filled_face->setCharacterRotationX( 0 );
|
||||
filled_face->setCharacterRotationY( 0 );
|
||||
filled_face->setCharacterRotationZ( 0 );
|
||||
filled_face->setStringRotation( 0 );
|
||||
|
||||
#ifndef OGLFT_NO_SOLID
|
||||
solid_face->setCharacterRotationX( 25. );
|
||||
solid_face->setCharacterRotationY( 25. );
|
||||
#endif
|
||||
solid_face->setCharacterRotationZ( 0 );
|
||||
solid_face->setStringRotation( 0 );
|
||||
|
||||
monochrome_texture_face->setCharacterRotationX( 0 );
|
||||
monochrome_texture_face->setCharacterRotationY( 0 );
|
||||
monochrome_texture_face->setCharacterRotationZ( 0 );
|
||||
monochrome_texture_face->setStringRotation( 0 );
|
||||
|
||||
grayscale_texture_face->setCharacterRotationX( 0 );
|
||||
grayscale_texture_face->setCharacterRotationY( 0 );
|
||||
grayscale_texture_face->setCharacterRotationZ( 0 );
|
||||
grayscale_texture_face->setStringRotation( 0 );
|
||||
|
||||
translucent_texture_face->setCharacterRotationX( 0 );
|
||||
translucent_texture_face->setCharacterRotationY( 0 );
|
||||
translucent_texture_face->setCharacterRotationZ( 0 );
|
||||
translucent_texture_face->setStringRotation( 0 );
|
||||
|
||||
glViewport( 0, 0, viewport_width, viewport_height );
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadIdentity();
|
||||
glOrtho( 0, viewport_width, 0, viewport_height, -100, 100 );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
static void char_rotate_x ( float dx )
|
||||
{
|
||||
outline_face->setCharacterRotationX( outline_face->characterRotationX()+dx );
|
||||
filled_face->setCharacterRotationX( filled_face->characterRotationX()+dx );
|
||||
#ifndef OGLFT_NO_SOLID
|
||||
solid_face->setCharacterRotationX( solid_face->characterRotationX()+dx );
|
||||
#endif
|
||||
monochrome_texture_face->setCharacterRotationX(
|
||||
monochrome_texture_face->characterRotationX()+dx );
|
||||
grayscale_texture_face->setCharacterRotationX(
|
||||
grayscale_texture_face->characterRotationX()+dx );
|
||||
translucent_texture_face->setCharacterRotationX(
|
||||
translucent_texture_face->characterRotationX()+dx );
|
||||
}
|
||||
|
||||
static void char_rotate_y ( float dy )
|
||||
{
|
||||
outline_face->setCharacterRotationY( outline_face->characterRotationY()+dy );
|
||||
filled_face->setCharacterRotationY( filled_face->characterRotationY()+dy );
|
||||
#ifndef OGLFT_NO_SOLID
|
||||
solid_face->setCharacterRotationY( solid_face->characterRotationY()+dy );
|
||||
#endif
|
||||
monochrome_texture_face->setCharacterRotationY(
|
||||
monochrome_texture_face->characterRotationY()+dy );
|
||||
grayscale_texture_face->setCharacterRotationY(
|
||||
grayscale_texture_face->characterRotationY()+dy );
|
||||
translucent_texture_face->setCharacterRotationY(
|
||||
translucent_texture_face->characterRotationY()+dy );
|
||||
}
|
||||
|
||||
static void char_rotate_z ( float dz )
|
||||
{
|
||||
monochrome_face->setCharacterRotationZ( monochrome_face->characterRotationZ()+dz );
|
||||
grayscale_face->setCharacterRotationZ( grayscale_face->characterRotationZ()+dz );
|
||||
translucent_face->setCharacterRotationZ( translucent_face->characterRotationZ()+dz );
|
||||
|
||||
outline_face->setCharacterRotationZ( outline_face->characterRotationZ()+dz );
|
||||
filled_face->setCharacterRotationZ( filled_face->characterRotationZ()+dz );
|
||||
solid_face->setCharacterRotationZ( solid_face->characterRotationZ()+dz );
|
||||
|
||||
monochrome_texture_face->setCharacterRotationZ( monochrome_texture_face->characterRotationZ()+dz );
|
||||
grayscale_texture_face->setCharacterRotationZ( grayscale_texture_face->characterRotationZ()+dz );
|
||||
translucent_texture_face->setCharacterRotationZ( translucent_texture_face->characterRotationZ()+dz );
|
||||
}
|
||||
|
||||
static void string_rotate ( float dz )
|
||||
{
|
||||
|
||||
monochrome_face->setStringRotation( monochrome_face->stringRotation()+dz );
|
||||
grayscale_face->setStringRotation( grayscale_face->stringRotation()+dz );
|
||||
translucent_face->setStringRotation( translucent_face->stringRotation()+dz );
|
||||
|
||||
outline_face->setStringRotation( outline_face->stringRotation()+dz );
|
||||
filled_face->setStringRotation( filled_face->stringRotation()+dz );
|
||||
solid_face->setStringRotation( solid_face->stringRotation()+dz );
|
||||
|
||||
monochrome_texture_face->setStringRotation( monochrome_texture_face->stringRotation()+dz );
|
||||
grayscale_texture_face->setStringRotation( grayscale_texture_face->stringRotation()+dz );
|
||||
translucent_texture_face->setStringRotation( translucent_texture_face->stringRotation()+dz );
|
||||
}
|
||||
|
||||
static void display ( void )
|
||||
{
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
glPushMatrix();
|
||||
|
||||
// Draw everything centered
|
||||
glTranslatef( viewport_width/2., 0., 0. );
|
||||
|
||||
commands_face->draw( 0., 0., commands );
|
||||
|
||||
glTranslatef( 0., dy, 0. );
|
||||
monochrome_face->draw( 0., 0., text );
|
||||
|
||||
glTranslatef( 0., dy, 0. );
|
||||
grayscale_face->draw( 0., 0., text );
|
||||
|
||||
glEnable( GL_BLEND );
|
||||
glTranslatef( 0., dy, 0. );
|
||||
translucent_face->draw( 0., 0., text );
|
||||
glDisable( GL_BLEND );
|
||||
|
||||
glTranslatef( 0., dy, 0. );
|
||||
outline_face->draw( 0., 0., text );
|
||||
|
||||
glTranslatef( 0., dy, 0. );
|
||||
filled_face->draw( 0., 0., text );
|
||||
|
||||
glTranslatef( 0., dy, 0. );
|
||||
#ifndef OGLFT_NO_SOLID
|
||||
glEnable( GL_LIGHTING );
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
solid_face->draw( 0., 0., text );
|
||||
glDisable( GL_COLOR_MATERIAL );
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glDisable( GL_LIGHTING );
|
||||
#else
|
||||
solid_face->draw( 0., 0., "<Note: Solid face not available in library>" );
|
||||
#endif
|
||||
|
||||
glEnable( GL_TEXTURE_2D );
|
||||
glEnable( GL_BLEND );
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
glTranslatef( 0., dy, 0. );
|
||||
monochrome_texture_face->draw( 0., 0., text );
|
||||
|
||||
glTranslatef( 0., dy, 0. );
|
||||
grayscale_texture_face->draw( 0., 0., text );
|
||||
|
||||
glTranslatef( 0., dy, 0. );
|
||||
translucent_texture_face->draw( 0., 0., text );
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glDisable( GL_BLEND );
|
||||
glDisable( GL_TEXTURE_2D );
|
||||
|
||||
glPopMatrix();
|
||||
glutSwapBuffers();
|
||||
}
|
||||
|
||||
static void key ( unsigned char key, int /*x*/, int /*y*/ )
|
||||
{
|
||||
switch ( key ) {
|
||||
case 'a':
|
||||
char_rotate_x( -4 ); break;
|
||||
case 'A':
|
||||
char_rotate_x( 4 ); break;
|
||||
case 's':
|
||||
char_rotate_y( -4 ); break;
|
||||
case 'S':
|
||||
char_rotate_y( 4 ); break;
|
||||
case 'd':
|
||||
char_rotate_z( -4 ); break;
|
||||
case 'D':
|
||||
char_rotate_z( 4 ); break;
|
||||
case 'f':
|
||||
string_rotate( -4 ); break;
|
||||
case 'F':
|
||||
string_rotate( 4 ); break;
|
||||
case 'r': case 'R':
|
||||
reset(); break;
|
||||
case 27:
|
||||
exit( 0 );
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
static void done ( void )
|
||||
{
|
||||
delete monochrome_face;
|
||||
delete grayscale_face;
|
||||
delete translucent_face;
|
||||
delete outline_face;
|
||||
delete filled_face;
|
||||
delete solid_face;
|
||||
delete monochrome_texture_face;
|
||||
delete grayscale_texture_face;
|
||||
delete translucent_texture_face;
|
||||
}
|
||||
|
||||
int main ( int argc, char* argv[] )
|
||||
{
|
||||
if ( argc != 2 ) {
|
||||
std::cerr << argv[0] << USAGE << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
glutInit( &argc, argv );
|
||||
glutInitWindowSize( 500, 500 );
|
||||
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
|
||||
glutCreateWindow( argv[0] );
|
||||
|
||||
init( argc, argv );
|
||||
|
||||
atexit( done );
|
||||
|
||||
glutReshapeFunc( reshape );
|
||||
glutDisplayFunc( display );
|
||||
glutKeyboardFunc( key );
|
||||
|
||||
glutMainLoop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* demo2.cpp: Second Demo of the OGLFT library
|
||||
* Copyright (C) 2002 lignum Computing, Inc. <oglft@lignumcomputing.com>
|
||||
* $Id$
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <iostream>
|
||||
|
||||
#include <GL/glut.h>
|
||||
|
||||
#include <OGLFT.h>
|
||||
|
||||
#include FT_MULTIPLE_MASTERS_H
|
||||
|
||||
static const char* USAGE = " fontfile";
|
||||
|
||||
static FT_Library library;
|
||||
static FT_Face ft_face;
|
||||
static FT_Multi_Master master_info;
|
||||
static FT_Long axis_averages[T1_MAX_MM_AXIS];
|
||||
#if 0
|
||||
static OGLFT::Filled* oglft_face;
|
||||
#else
|
||||
static OGLFT::Monochrome* oglft_face;
|
||||
#endif
|
||||
static int viewport_width;
|
||||
static int viewport_height;
|
||||
|
||||
static void init ( int /*argc*/, char* argv[] )
|
||||
{
|
||||
std::cout << glGetString( GL_VENDOR ) << " " << glGetString( GL_RENDERER ) << " "
|
||||
<< glGetString( GL_VERSION ) << std::endl;
|
||||
|
||||
library = OGLFT::Library::instance();
|
||||
|
||||
FT_Error error;
|
||||
|
||||
error = FT_New_Face( library, argv[1], 0, &ft_face );
|
||||
|
||||
if ( error != 0 ) {
|
||||
std::cerr << "Could not create a font from file \"" << argv[1] << "\""
|
||||
<< std::endl;
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
error = FT_Get_Multi_Master( ft_face, &master_info );
|
||||
|
||||
if ( error != 0 ) {
|
||||
std::cerr << "Font file \"" << argv[1]
|
||||
<< "\" does not contain a multi master font" << std::endl;
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
for ( unsigned int i = 0; i < master_info.num_axis; i++ )
|
||||
axis_averages[i] = ( master_info.axis[i].minimum +
|
||||
master_info.axis[i].maximum ) / 2;
|
||||
|
||||
FT_Set_MM_Design_Coordinates( ft_face, master_info.num_axis, axis_averages );
|
||||
|
||||
#if 0
|
||||
oglft_face = new OGLFT::Filled( ft_face, 14 );
|
||||
#else
|
||||
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
|
||||
glEnable( GL_RASTER_POSITION_UNCLIPPED_IBM );
|
||||
|
||||
oglft_face = new OGLFT::Monochrome( ft_face, 14 );
|
||||
#endif
|
||||
oglft_face->setHorizontalJustification( OGLFT::Face::LEFT );
|
||||
oglft_face->setForegroundColor( 1., 0., 0. );
|
||||
oglft_face->setCompileMode( OGLFT::Face::IMMEDIATE );
|
||||
}
|
||||
|
||||
static void reshape ( int width, int height )
|
||||
{
|
||||
viewport_width = width;
|
||||
viewport_height = height;
|
||||
|
||||
glViewport( 0, 0, viewport_width, viewport_height );
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadIdentity();
|
||||
glOrtho( 0, viewport_width, 0, viewport_height, -100, 100 );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
static void display ( void )
|
||||
{
|
||||
const int BUFSIZE = 128;
|
||||
char buffer[BUFSIZE];
|
||||
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
glPushMatrix();
|
||||
|
||||
snprintf( buffer, sizeof(buffer), "There are %d axes", master_info.num_axis );
|
||||
|
||||
GLfloat y = 480.;
|
||||
|
||||
oglft_face->draw( 0., y, buffer );
|
||||
|
||||
for ( unsigned int i = 0; i < master_info.num_axis; i++ ) {
|
||||
FT_Set_MM_Design_Coordinates( ft_face, master_info.num_axis, axis_averages );
|
||||
snprintf( buffer, sizeof(buffer), "%s: min: %ld max: %ld",
|
||||
master_info.axis[i].name,
|
||||
master_info.axis[i].minimum, master_info.axis[i].maximum );
|
||||
|
||||
y -= 20.;
|
||||
oglft_face->draw( 0., y, buffer );
|
||||
|
||||
FT_Long axis_average = axis_averages[i];
|
||||
FT_Long d_axis = (master_info.axis[i].maximum - master_info.axis[i].minimum)/4;
|
||||
axis_averages[i] = master_info.axis[i].minimum;
|
||||
|
||||
for ( int j = 0; j <= 4; j++ ) {
|
||||
FT_Set_MM_Design_Coordinates( ft_face, master_info.num_axis, axis_averages );
|
||||
snprintf( buffer, sizeof(buffer), " Style at axis = %ld\n", axis_averages[i] );
|
||||
y -= 20.;
|
||||
oglft_face->draw( 0., y, buffer );
|
||||
|
||||
axis_averages[i] += d_axis;
|
||||
}
|
||||
|
||||
axis_averages[i] = axis_average;
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
glutSwapBuffers();
|
||||
}
|
||||
|
||||
static void key ( unsigned char key, int /*x*/, int /*y*/ )
|
||||
{
|
||||
switch ( key ) {
|
||||
case 'q':
|
||||
case 27:
|
||||
exit( 0 );
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
static void done ( void )
|
||||
{
|
||||
}
|
||||
|
||||
int main ( int argc, char* argv[] )
|
||||
{
|
||||
if ( argc != 2 ) {
|
||||
std::cerr << argv[0] << USAGE << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
glutInit( &argc, argv );
|
||||
glutInitWindowSize( 500, 500 );
|
||||
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
|
||||
glutCreateWindow( argv[0] );
|
||||
|
||||
init( argc, argv );
|
||||
|
||||
atexit( done );
|
||||
|
||||
glutReshapeFunc( reshape );
|
||||
glutDisplayFunc( display );
|
||||
glutKeyboardFunc( key );
|
||||
|
||||
glutMainLoop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/* -*- c++ -*-
|
||||
* speedtest.h: Header for Performance test for the OGLFT library
|
||||
* Copyright (C) 2002 lignum Computing, Inc. <oglft@lignumcomputing.com>
|
||||
* $Id$
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef SPEEDTEST_H
|
||||
#define SPEEDTEST_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <qgl.h>
|
||||
#include <qqueue.h>
|
||||
#include <qtimer.h>
|
||||
|
||||
// Little animation vignettes. The function calls essentially follow
|
||||
// those of the Qt OpenGL widget and are called at the corresponding times.
|
||||
|
||||
struct Vignette {
|
||||
virtual ~Vignette ( void ) {}
|
||||
virtual unsigned int frame_count ( void ) = 0;
|
||||
virtual void init ( void ) = 0;
|
||||
virtual void view ( GLdouble /*left*/, GLdouble /*right*/,
|
||||
GLdouble /*bottom*/, GLdouble /*top*/ )
|
||||
{}
|
||||
virtual void reset ( void )
|
||||
{}
|
||||
virtual bool input ( QKeyEvent* e )
|
||||
{
|
||||
if ( e->key() == Qt::Key_Escape ) exit( 0 );
|
||||
return false;
|
||||
}
|
||||
virtual void draw ( int frame_number ) = 0;
|
||||
virtual void finish ( void ) = 0;
|
||||
};
|
||||
|
||||
// Yet another OpenGL view widget.
|
||||
|
||||
class CharacterView : public QGLWidget {
|
||||
Q_OBJECT
|
||||
GLsizei window_width_, window_height_;
|
||||
GLdouble view_width_, view_height_;
|
||||
GLdouble view_left_, view_right_, view_bottom_, view_top_;
|
||||
GLdouble rot_x_, rot_y_, rot_z_;
|
||||
|
||||
QTimer redraw_timer_;
|
||||
QTimer performance_timer_;
|
||||
|
||||
unsigned int frame_counter_;
|
||||
unsigned int counter_snapshot_;
|
||||
unsigned int animation_frame_count_;
|
||||
unsigned int iteration_counter_;
|
||||
unsigned int maximum_iterations_;
|
||||
|
||||
static const unsigned int PERFORMANCE_SAMPLE_RATE_HZ = 1;
|
||||
static const unsigned int MAXIMUM_ITERATIONS = 4;
|
||||
|
||||
QQueue<Vignette> vignettes;
|
||||
|
||||
protected slots:
|
||||
void redraw ( void );
|
||||
void measure_performance ( void );
|
||||
|
||||
public:
|
||||
CharacterView ( const char* text, const char* fontfile,
|
||||
QWidget* parent = 0, const char* name = 0 );
|
||||
protected:
|
||||
|
||||
void initializeGL ( void );
|
||||
void resizeGL ( int w, int h );
|
||||
void paintGL ( void );
|
||||
void keyPressEvent ( QKeyEvent* e );
|
||||
void resetView ( void );
|
||||
};
|
||||
|
||||
#endif /* SPEEDTEST_H */
|
||||
|
After Width: | Height: | Size: 507 B |
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
|
||||
# Convert the file given on the commandline into something which
|
||||
# can be compiled with C and linked into an executable.
|
||||
# Use the generated object module with the following declarations:
|
||||
# extern unsigned char ${ARGV[0]}[]; /* Array of data */
|
||||
# extern int ${ARGV[0]}_size; /* Size of array */
|
||||
# Note, .'s in the argument filename are converted to _'s
|
||||
|
||||
open FILE, $ARGV[0] or die "usage: $0 file";
|
||||
|
||||
# "Slurp the whole file"
|
||||
undef $/;
|
||||
my $contents = <FILE>;
|
||||
|
||||
# Replace .'s in the filename with _'s (since . is an operator in C)
|
||||
my $label = $ARGV[0];
|
||||
$label =~ s/\./_/;
|
||||
|
||||
print "FT_Byte $label\[\] = {\n";
|
||||
|
||||
for ( my $i = 0; $i < length $contents; $i += 16 ) {
|
||||
print join( ",", unpack( "C*", substr( $contents, $i, 16 ) ) ), ",\n";
|
||||
}
|
||||
|
||||
print "};\n";
|
||||
|
||||
print "const int ${label}_size = sizeof( $label );\n";
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* tutorial1.cpp: Tutorial for the OGLFT library
|
||||
* Copyright (C) 2002 lignum Computing, Inc. <oglft@lignumcomputing.com>
|
||||
* $Id$
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <iostream>
|
||||
|
||||
#include <GL/glut.h>
|
||||
|
||||
#include <OGLFT.h> // Note: this will depend on where you've installed OGLFT
|
||||
|
||||
// Declare a Face variable of the desired style
|
||||
OGLFT::Monochrome* monochrome;
|
||||
|
||||
void init ( const char* filename )
|
||||
{
|
||||
// Create a new face given the font filename and a size
|
||||
|
||||
monochrome = new OGLFT::Monochrome( filename, 36 );
|
||||
|
||||
// Always check to make sure the face was properly constructed
|
||||
|
||||
if ( monochrome == 0 || !monochrome->isValid() ) {
|
||||
std::cerr << "Could not construct face from " << filename << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the face color to red
|
||||
|
||||
monochrome->setForegroundColor( 1., 0., 0. );
|
||||
|
||||
// For the raster styles, it is essential that the pixel store
|
||||
// unpacking alignment be set to 1
|
||||
|
||||
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
|
||||
|
||||
// Set the window's background color
|
||||
|
||||
glClearColor( .75, .75, .75, 1. );
|
||||
}
|
||||
|
||||
static void display ( void )
|
||||
{
|
||||
// First clear the window ...
|
||||
glClear( GL_COLOR_BUFFER_BIT );
|
||||
// ... then draw the string
|
||||
monochrome->draw( 0., 250., "Hello, World!" );
|
||||
}
|
||||
|
||||
static void reshape ( int width, int height )
|
||||
{
|
||||
glViewport( 0, 0, width, height );
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadIdentity();
|
||||
glOrtho( 0, width, 0, height, -1, 1 );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
int main ( int argc, char* argv[] )
|
||||
{
|
||||
// Check to be sure the user specified something as a font file name
|
||||
|
||||
if ( argc != 2 ) {
|
||||
std::cerr << "usage: " << argv[0] << " fontfile" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Standard GLUT setup commands
|
||||
|
||||
glutInit( &argc, argv );
|
||||
glutInitWindowSize( 500, 500 );
|
||||
glutInitDisplayMode( GLUT_RGB ); // Note: OGLFT really only works in RGB mode
|
||||
glutCreateWindow( argv[0] );
|
||||
|
||||
init( argv[1] );
|
||||
|
||||
glutReshapeFunc( reshape );
|
||||
glutDisplayFunc( display );
|
||||
glutMainLoop();
|
||||
|
||||
return 0;
|
||||
}
|
||||