first commit

This commit is contained in:
2026-06-22 11:49:35 +02:00
commit d805f2ba86
619 changed files with 126873 additions and 0 deletions

View File

@ -0,0 +1,82 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NASCIIENC__
#define __NASCIIENC__
#include "ntypes.h"
/*!
@short ASCII encoding.
This class currently provide two commonly used encoding method:
yEnc and UUEncode.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
namespace nAsciiEncoder
{
/*!
@short Perform UUEncoding.
@param source Input binary stream.
@param len Input binary stream length.
@param uuenc Output buffer.
@param max Output buffer length.
@return The number of bytes written to the output buffer.
@note If yenc is NULL the function can be used to check the size
of the encoded stream prior to allocating an output buffer.
*/
uint UUEncode(const uchar *source, size_t len, uchar *uuenc = 0, size_t max = 0);
/*!
@short Perform UUDecoding.
@param source UUEncoded byte stream.
@param len UUEncoded byte stream length.
@param bin Output buffer.
@param max Output buffer length.
@return The number of bytes written to the output buffer.
@note If bin is NULL the function can be used to check the size
of the decoded stream prior to allocating an output buffer.
*/
uint UUDecode(const uchar *source, size_t len, uchar *bin = 0, size_t max = 0);
/*!
@short Perform yEncoding.
@param source Input binary stream.
@param len Input binary stream length.
@param yenc Output buffer.
@param max Output buffer length.
@param line_len Number of character to output before a line-feed character is sent.
@return The number of bytes written to the output buffer.
@note If yenc is NULL the function can be used to check the size
of the encoded stream prior to allocating an output buffer.
*/
uint yEncode(const uchar *source, size_t len, uchar *yenc = 0, size_t max = 0, uint line_len = 64);
/*!
@short Perform yDecoding.
@param source yEncoded byte stream.
@param len yEncoded byte stream length.
@param bin Output buffer.
@param max Output buffer length.
@return The number of bytes written to the output buffer.
@note If bin is NULL the function can be used to check the size
of the decoded stream prior to allocating an output buffer.
*/
uint yDecode(const uchar *source, size_t len, uchar *bin = 0, size_t max = 0);
};
#endif // __NASCIIENC__

View File

@ -0,0 +1,50 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
------------------------------------------------------------------------------*/
#ifndef __NASCII_PARSER__
#define __NASCII_PARSER__
/*!
@short ASCII parsing tools.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
namespace GS {
namespace AsciiParser {
/// Return true is the provided character is uppercase.
bool IsUpperCase(const char s);
/// Return whether a constant is float or int.
bool IsConstantFloat(const char *s, const char *e);
/// Find a character inside an ASCII block.
const char *Find(const char *s, const char *e, char f);
/// Run to end of string.
const char *RunToEOS(const char *s, const char *e);
/// Run to end of line marker.
const char *RunToEOL(const char *s, const char *e);
/// Skip end of line marker.
const char *SkipEOL(const char *s, const char *e);
/*!
@short Run to the end of a group started with character 'op' closed with character 'cl'.
@note This function automatically skips nested group of the same kind.
*/
const char *RunToEOG(const char *s, const char *e, char op, char cl);
/// Run to the end of a C comment block (/*...*/).
const char *RunToEOC(const char *s, const char *e);
/// Run to the end of a C expression.
const char *RunToEOE(const char *s, const char *e);
/// Skip non-{space/tab/comments} string.
const char *SkipEntry(const char *s, const char *e, bool skip_minus = false);
/// Skip spaces.
const char *SkipSpace(const char *s, const char *e);
/// Go to the next entry.
const char *NextEntry(const char *s, const char *e, bool skip_minus = false);
}
}
#endif // __NASCII_PARSER__

View File

@ -0,0 +1,47 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __AUDIOIO__
#define __AUDIOIO__
#include "audio/stream_interface.h"
#include "audio/stream_factory.h"
#include "audio/sample_interface.h"
#include "audio/sample_factory.h"
#include "memory/singleton.h"
#include "container/nlist.h"
namespace GS {
/*
@short Audio factory.
@author Emmanuel Julien (ejulien@owloh.com)
*/
class AudioIO : public Singleton <AudioIO>
{
AutoList <IAudioStreamFactory *> stream_factories;
AutoList <ISampleFactory *> sample_factories;
public:
/// Register a stream codec.
void RegisterStreamFactory(IAudioStreamFactory *);
/// Register a sample codec.
void RegisterSampleFactory(ISampleFactory *);
/// Open stream.
IAudioStream *OpenStream(const char *path, const char *format = 0);
/// Load a sample.
ISample *LoadSample(const char *path, const char *format = 0);
};
} // GS
#endif // __AUDIOIO__

View File

@ -0,0 +1,32 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __ISAMPLEFACTORY__
#define __ISAMPLEFACTORY__
namespace GS {
struct ISample;
/*
@short Sample I/O codec interface.
@author Emmanuel Julien (ejulien@owloh.com)
*/
struct ISampleFactory
{
/// Get the codec name.
virtual const char *GetName() = 0;
/// Load a sample.
virtual ISample *Load(const char *path) = 0;
virtual ~ISampleFactory() {}
};
} // GS
#endif // __ISAMPLEFACTORY__

View File

@ -0,0 +1,46 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NSAMPLEFORMAT__
#define __NSAMPLEFORMAT__
#include "ntypes.h"
namespace GS {
/*!
@short Sample format.
@author Emmanuel Julien (ejulien@nworks.fr)
*/
struct SampleFormat
{
enum Format
{
Format_PCM = 0,
#if __PLATFORM_NINTENDO_WII__
Format_Wii_ADPCM
#endif
};
Format format;
uint channels;
uint frequency;
uchar resolution;
/// Get the PCM data memory footprint a given number of samples in this format.
uint GetPCMDataSize(uint sample_count) const
{ return (sample_count * channels * resolution) / 8; }
SampleFormat(Format _format = Format_PCM, uint _channels = 2, uint _frequency = 48000, uchar _bit_per_sample = 16) : format(_format), channels(_channels), frequency(_frequency), resolution(_bit_per_sample) {}
};
} // GS
#endif // __NSAMPLEFORMAT__

View File

@ -0,0 +1,37 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __ISAMPLE__
#define __ISAMPLE__
#include "audio/sample_format.h"
#include "time/ntime.h"
namespace GS {
/*!
@short Sample base interface.
@author Emmanuel Julien (ejulien@nworks.fr)
*/
struct ISample
{
/// Return the format identifier (eg. "WAV").
virtual const char *GetFormat() = 0;
/// Get sample format.
virtual bool GetSampleFormat(SampleFormat &) const = 0;
/// Get sample duration.
virtual Time GetDuration() const = 0;
virtual ~ISample() {}
};
} // GS
#endif // __ISAMPLE__

View File

@ -0,0 +1,34 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __SAMPLESTREAMFACTORY__
#define __SAMPLESTREAMFACTORY__
#include "audio/sample_interface.h"
#include "audio/sample_factory.h"
namespace GS {
struct ISample;
/*!
@short Sample stream factory
This codec can decode any supported audio stream to a WAV sample.
@author Emmanuel Julien (ejulien@owloh.com)
*/
struct SampleStreamFactory : public ISampleFactory
{
/// Get the codec name.
virtual const char *GetName() { return "Stream"; }
/// Load a sample.
virtual ISample *Load(const char *path);
};
} // GS
#endif // __SAMPLESTREAMFACTORY__

View File

@ -0,0 +1,60 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __SAMPLEWAV__
#define __SAMPLEWAV__
#include "audio/sample_interface.h"
#include "time/ntime.h"
namespace GS {
/*!
@short WAV sample.
@author Emmanuel Julien (ejulien@owloh.com)
*/
class SampleWav : public ISample
{
friend struct SampleWavFactory;
protected:
SampleFormat format;
uint sample_count;
Array <char> pcm_data;
public:
/// Return the sample count.
uint GetSampleCount() const { return sample_count; }
/// Return the PCM data.
void *GetPCMData() const { return pcm_data.c_ptr(); }
/// Return the PCM data size.
uint GetPCMDataSize() const;
/// Set PCM data, the data array content will be transfered to the sample.
void Set(Array <char> &data, uint sample_count, const SampleFormat &);
/// Allocate PCM samples for a given format.
char *AllocAs(uint sample_count, const SampleFormat &);
/// Return the sample format identifier (eg. "WAV").
virtual const char *GetFormat() { return "WAV"; }
/// Get the sample format.
virtual bool GetSampleFormat(SampleFormat &) const;
/// Get sample duration.
virtual Time GetDuration() const;
SampleWav() : sample_count(0) {}
};
} // GS
#endif // __SAMPLEWAV__

View File

@ -0,0 +1,29 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __SAMPLEWAVCODEC__
#define __SAMPLEWAVCODEC__
#include "audio/sample_factory.h"
namespace GS {
struct ISample;
/// Sample WAV codec
struct SampleWavFactory : public ISampleFactory
{
/// Get the codec name.
virtual const char *GetName() { return "WAV"; }
/// Load a sample.
virtual ISample *Load(const char *path);
};
} // GS
#endif // __SAMPLEWAVCODEC__

View File

@ -0,0 +1,31 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __ISTREAMFACTORY__
#define __ISTREAMFACTORY__
namespace GS {
struct IAudioStream;
/*
@short Stream factory interface.
@author Emmanuel Julien (ejulien@owloh.com)
*/
struct IAudioStreamFactory
{
/// Get factory name.
virtual const char *GetName() = 0;
/// Open a stream.
virtual IAudioStream *Open(const char *path) = 0;
virtual ~IAudioStreamFactory() {}
};
} // GS
#endif // __ISTREAMFACTORY__

View File

@ -0,0 +1,42 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __AUDIOSTREAMINTERFACE__
#define __AUDIOSTREAMINTERFACE__
#include "audio/sample_format.h"
namespace GS {
/*
@short Audio stream interface.
@author Emmanuel Julien (ejulien@nworks.fr)
*/
struct IAudioStream
{
SampleFormat format;
/// Return the stream data format (eg. "OGG").
virtual const char *GetFormat() = 0;
virtual bool Seek(int t_ms = 0) = 0;
virtual bool IsEOF() const = 0;
virtual size_t GetPCM(void *) = 0;
virtual size_t GetPCMBufferSize() const = 0;
virtual bool Open(const char *uri) = 0;
virtual void Close() = 0;
virtual ~IAudioStream() {}
};
} // GS
#endif // __AUDIOSTREAMINTERFACE__

140
include/framework/bih/bih.h Normal file
View File

@ -0,0 +1,140 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NBIH__
#define __NBIH__
#include "geometry/bounding_box.h"
#include "container/narray.h"
#include "memory/nauto_ptr.h"
namespace GS {
namespace BIH {
// Bounding interval hierarchy node.
struct Node
{
char axis; ///< @TODO: Packed bitfield!
void *p; ///< Pointer to child nodes or index array.
union
{
uint count; ///< Index count in leaf.
float split[2]; ///< Split planes.
};
Node() : axis(3), p(0) {}
~Node();
};
struct StackEntry
{
Node *node;
float tmin, tmax;
};
//
struct Trace
{
StackEntry stack[65];
uint stack_pos;
bool want_closest;
bool has_i; ///< Do we have an intersection.
float i_t; ///< Distance to intersection from ray's origin.
Vector4 s; ///< Ray origin.
Vector4 d; ///< Ray direction.
uint node_visited; ///< Number of nodes visited.
Trace(bool closest = true) : want_closest(closest), has_i(false) {}
};
/*!
@short Bounding interval hierarchy.
This is a fully generic bounding interval hierarchy implementation.
In order to use this structure on a custom set of data you need to derive
from this class and provide the implementation for the TraceLeaf method.
In order to build the structure you simply provide a list of volumes to the
build() methods.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
class Tree
{
protected:
/// Minimum leaf volume count.
uint min_leaf_vcount;
MinMax minmax; ///< Hierarchy bounding box.
AutoPtr <Node> root; ///< Hierarchy root node.
Array <uint> sarray; ///< Index array.
uint node_count;
uint leaf_count;
uint depth;
/*!
@name Trace functions.
@{
*/
/// Trace a leaf.
virtual void TraceLeaf(Node *leaf, float tmin, float tmax, Trace &trace, void *parm = 0) = 0;
/// Trace a node.
void TraceNode(Node *node, float tmin, float tmax, Trace &trace);
/// @}
/*!
@name Intersection functions.
@{
*/
/// Intersect a node.
uint IntersectNode(Node *node, MinMax &sub_mm, uint *index_array, uint max_index);
/// @}
/*!
@name Build functions.
@{
*/
/// Create a leaf.
void MakeNodeLeaf(Node *node, uint count, uint *sarray, MinMax *varray);
/// Perform a node split.
void DoNodeSplit(MinMax &minmax, uint count, uint *sarray, MinMax *varray, uint &pivot, Node *node, uint &split_axis);
/// Split an index list of volumes.
bool Split(MinMax &minmax, uint count, uint *sarray, MinMax *varray, Node *node, uint depth);
/// Build hierarchy from a set of input volumes.
virtual bool Build(uint volume_count, MinMax *varray);
/// @}
public:
/// Intersect tree with an axis aligned bounding box.
uint Intersect(MinMax &minmax, uint *index_array, uint max_index);
/*
@short Raytrace hierarchy.
@note Ray direction must be normalized.
*/
virtual void Raytrace(Trace &trace, const Vector4 &s, const Vector4 &d, float l = -1.f, void *parm = 0);
/// Delete hierarchy.
virtual void Free();
Tree();
virtual ~Tree();
};
} // BIH
} // GS
#endif // __NBIH__

View File

@ -0,0 +1,106 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NCOLOR__
#define __NCOLOR__
#include "math/vector.h"
namespace GS {
/*!
@short The base color object.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
struct Color : public Vector4
{
bool operator == (const Vector4 &b) const { return Math::TestEqual(x, b.x) && Math::TestEqual(y, b.y) && Math::TestEqual(z, b.z) && Math::TestEqual(w, b.w); }
bool operator != (const Vector4 &b) const { return !Math::TestEqual(x, b.x) || !Math::TestEqual(y, b.y) || !Math::TestEqual(z, b.z) || !Math::TestEqual(w, b.w); }
/// Standard C++ operators.
void operator += (const Color &b) { x += b.x; y += b.y; z += b.z; w += b.w; };
void operator += (const float k) { x += k; y += k; z += k; w += k; };
void operator -= (const Color &b) { x -= b.x; y -= b.y; z -= b.z; w -= b.w; };
void operator -= (const float k) { x -= k; y -= k; z -= k; w -= k; };
void operator *= (const Color &b) { x *= b.x; y *= b.y; z *= b.z; w *= b.w; };
void operator *= (const float k) { x *= k; y *= k; z *= k; w *= k; };
void operator /= (const Color &b) { x /= b.x; y /= b.y; z /= b.z; w /= b.w; };
void operator /= (const float k) { float k_ = 1.0f / k; x *= k_; y *= k_; z *= k_; w *= k_; };
Color operator + (const Color &b) const { return Color(x + b.x, y + b.y, z + b.z, w + b.w); }
Color operator + (const float v) const { return Color(x + v, y + v, z + v, w + v); }
Color operator - (const Color &b) const { return Color(x - b.x, y - b.y, z - b.z, w - b.w); }
Color operator - (const float v) const { return Color(x - v, y - v, z - v, w - v); }
Color operator * (const Color &b) const { return Color(x * b.x, y * b.y, z * b.z, w * b.w); }
Color operator * (const float v) const { return Color(x * v, y * v, z * v, w * v); }
Color operator / (const Color &b) const { return Color(x / b.x, y / b.y, z / b.z, w / b.w); }
Color operator / (const float v) const { return Color(x / v, y / v, z / v, w / v); }
void operator = (const Vector4 &v) { x = v.x; y = v.y; z = v.z; w = v.w; }
/*!
@short Return a grayscale value representing this color.
The grayscale value is computed accounting for the human eye color intensity perception.
@see FastGray().
*/
inline float Grayscale() const
{ return 0.3f * x + 0.59f * y + 0.11f * z; }
/*!
@short Return a grayscale value representing this color.
@note This function is not optically accurate.
@see Grayscale().
*/
inline float Fastgray() const
{ return (x + y + z) / 3.f; }
/// Return the color object as an RGBA value.
uint AsInteger() const;
/// Load the color object from an RGBA value.
void FromInteger(uint value);
/*!
@name Static color objects.
@{
*/
static Color White;
static Color Grey;
static Color Black;
static Color Red;
static Color Green;
static Color Blue;
static Color Yellow;
static Color Purple;
/// @}
/// Scale color not alpha.
Color ScaleChroma(float k) const
{ return Color(x * k, y * k, z * k, w); }
/// Return a color object from a vector object.
static Color FromVector(Vector4 &v)
{ return Color(v.x, v.y, v.z, v.w); }
static uint ARGBtoRGBA(uint argb)
{ return ((argb & 0xff) << 24) + (((argb >> 8) & 0xff) << 16) + (((argb >> 16) & 0xff) << 8) + ((argb >> 24) & 0xff); }
Color(const Vector4 &v)
{ *this = v; }
Color(uint rgba32)
{ FromInteger(rgba32); }
Color(float r, float g, float b, float a = 1) : Vector4(r, g, b, a) {}
Color() {}
};
} // GS
#endif // __NCOLOR__

View File

@ -0,0 +1,136 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NVARIANT__
#define __NVARIANT__
#include "nstring/nstring.h"
namespace GS {
/*!
@short Base property.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
class Variant
{
public:
enum Type
{
VariantNone = 0,
VariantFloat,
VariantBool,
VariantInteger,
VariantString,
VariantBinary
};
protected:
void Reset();
public:
/*!
@name Property value.
@{
*/
Type type;
union
{
char *d_value;
bool b_value;
float f_value;
int i_value;
uint u_value;
};
size_t d_size; /// Binary data size.
String s_value;
/// @}
String id; ///< Variant id.
bool operator < (const Variant &b) const;
bool operator > (const Variant &b) const;
bool operator == (const Variant &b) const;
bool operator != (const Variant &b) const;
Variant &operator = (bool v);
Variant &operator = (int v);
Variant &operator = (uint v);
Variant &operator = (const char *v);
Variant &operator = (float v);
Variant &operator = (const Variant &v);
/// Get property type.
Type GetType() const { return type; }
/// Free current property value.
void Free();
/// Get string value.
bool Get(const char * &v) const;
/// Get bool value.
bool Get(bool &v) const;
/// Get integer value.
bool Get(int &v) const;
/// Get unsigned value.
bool Get(uint &v) const;
/// Get float value.
bool Get(float &v) const;
/// Set binary data.
bool SetBinary(const void *data, size_t size);
/// Get binary data.
bool GetBinary(void *&data, size_t &size) const;
/// Direct access to the binary buffer.
void *GetBinaryBuffer() const { return GetType() == VariantBinary ? (void *)d_value : 0; }
/// Binary buffer size.
size_t GetBinarySize() const { return GetType() == VariantBinary ? d_size : 0; }
/// Get children array.
bool Get(List <Variant *> &a);
Variant(const char *v)
{ Reset(); *this = v; }
Variant(bool v)
{ Reset(); *this = v; }
Variant(int v)
{ Reset(); *this = v; }
Variant(uint v)
{ Reset(); *this = v; }
Variant(float v)
{ Reset(); *this = v; }
Variant(void *d, size_t l)
{ Reset(); SetBinary(d, l); }
Variant(const char *i, const char *v)
{ Reset(); id = i; *this = v; }
Variant(const char *i, bool v)
{ Reset(); id = i; *this = v; }
Variant(const char *i, int v)
{ Reset(); id = i; *this = v; }
Variant(const char *i, uint v)
{ Reset(); id = i; *this = v; }
Variant(const char *i, float v)
{ Reset(); id = i; *this = v; }
Variant()
{ Reset(); }
~Variant();
};
}
#endif // __NVARIANT__

View File

@ -0,0 +1,65 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NREGISTRY__
#define __NREGISTRY__
#include "metafile/nml.h"
#include "messaging/messaging.h"
namespace GS {
enum RegistryMessage
{
RegistryMsg_None = 0, ///< No message.
RegistryMsg_StartKeyChangeBatch,
RegistryMsg_KeyChange,
RegistryMsg_EndKeyChangeBatch
};
enum RegistryRValue
{
RegistryReturn_Ok = 0
};
//
struct RegistryKeyChange
{
String key;
RegistryKeyChange(const char *k) { key = String(k).TrimChar(';'); }
};
struct Registry;
/// Registry listener.
struct RegistryListener
{
virtual RegistryRValue ProcessMessage(RegistryMessage message, const Registry *from, const void *parm) = 0;
virtual ~RegistryListener() {}
};
/*
@short Registry.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
struct Registry : public Messaging::Broadcaster <RegistryMessage, RegistryListener, Registry *>, public NML::File
{
NML::Tag *CreateKey(const char *path, const Variant *value = 0, bool recursive = true);
NML::Tag *CreateKey(const char *path, const Variant &value, bool recursive = true);
bool DeleteKey(const char *path);
/// Get the float value of a given key.
float GetReal(const char *path, float default_value = 0) const;
/// Get the boolean value of a given key.
bool GetBool(const char *path, bool default_value = false) const;
};
} // GS
#endif // __NREGISTRY__

View File

@ -0,0 +1,56 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
------------------------------------------------------------------------------*/
#ifndef __FONTCACHE__
#define __FONTCACHE__
#include "font/font_factory.h"
#include "font/font_extended.h"
#include "memory/nauto_ptr.h"
#include "memory/nweak_ptr.h"
#include "container/nlist.h"
namespace GS {
/// Extended font alias.
struct FontAlias
{
String alias;
sFontEx font;
};
/*
@short Font cache.
@author Emmanuel Julien (ejulien@nworks.fr)
*/
class FontCache : public SharedObject
{
AutoList <FontAlias *> font_aliases;
AutoPtr <IFontFactory> font_factory;
public:
FontEx *GetFont(const char *) const;
FontAlias *GetAlias(const char *) const;
FontEx *GetAliasedFont(const char *) const;
FontEx *LoadFont(const char *, const char *alias = 0);
void DeleteAlias(const char *);
void DeleteAllFont();
FontCache(IFontFactory *factory) : font_factory(factory) {}
~FontCache();
};
typedef SharedPtr <FontCache> sFontCache;
} // GS
#endif // __FONTCACHE__

View File

@ -0,0 +1,70 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
------------------------------------------------------------------------------*/
#ifndef __FONTEXTENDED__
#define __FONTEXTENDED__
#include "font/font_interface.h"
#include "memory/nauto_ptr.h"
#include "memory/nweak_ptr.h"
namespace GS {
/*!
@short Extended font to help normalization.
@author Emmanuel Julien (ejulien@owloh.com)
*/
class FontEx : public IFont
{
sIFont font;
WeakPtr <IFont> current_glyph_font;
int pixel_size;
public:
WeakPtr <IFont> fallback; ///< Fall-back font when a glyph is not found in the current font.
float size_multiplier, ///< Offsets to ease TTF normalization.
tracking_offset,
leading_offset;
/// Return the font name.
const char *GetName() const { return font->GetName(); }
/// Return the bounding rect for a given string.
iRect GetTextBoundRect(const char *text) const { return font->GetTextBoundRect(text); }
/// Set font size in pixels.
bool SetPixelSize(int);
/// Get font height in pixels.
int GetHeight() const;
/// Get font current glyph advance.
int GetAdvance() const;
/// Return true if the font supports kerning.
bool HasKerning() const;
/// Return the kerning for a glyph pair.
int GetKerning(uint previous_glyph, uint glyph) const;
/// Load the glyph corresponding to a UTF-32 codepoint.
bool LoadGlyph(uint codepoint, bool for_render);
/// Render currently loaded glyph to a picture.
bool RenderCurrentGlyph(Picture &picture, const iPoint &position, const iRect &clip, const Color &color);
/// Set a fallback font to query in case a glyph cannot be found in this font.
void SetFallback(IFont *f) { fallback = f; }
FontEx(IFont *f) : font(f), size_multiplier(1), tracking_offset(1), leading_offset(1) {}
};
typedef SharedPtr <FontEx> sFontEx;
} // GS
#endif // __FONTEXTENDED__

View File

@ -0,0 +1,26 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
------------------------------------------------------------------------------*/
#ifndef __FONTFACTORY__
#define __FONTFACTORY__
namespace GS {
struct IFont;
/// Font factory.
struct IFontFactory
{
/// Load a font.
virtual IFont *LoadFont(const char *) = 0;
virtual ~IFontFactory() {}
};
} // GS
#endif // __FONTFACTORY__

View File

@ -0,0 +1,60 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __FONTINTERFACE__
#define __FONTINTERFACE__
#include "color/color.h"
#include "geometry/rect.h"
#include "memory/nshared_ptr.h"
#include "nstring/nstring.h"
namespace GS {
class Picture;
/*!
@short Font interface.
@author Emmanuel Julien (ejulien@owloh.com)
*/
struct IFont : public SharedObject
{
/// Return the font name.
virtual const char *GetName() const = 0;
/// Return the bounding rect for a given string.
virtual iRect GetTextBoundRect(const char *) const = 0;
/// Set font size in pixels.
virtual bool SetPixelSize(int) = 0;
/// Get font height in pixels.
virtual int GetHeight() const = 0;
/// Get font current glyph advance.
virtual int GetAdvance() const = 0;
/// Return true if the font supports kerning.
virtual bool HasKerning() const = 0;
/// Return the kerning for a glyph codepoint.
virtual int GetKerning(uint previous_codepoint, uint codepoint) const = 0;
/// Load the glyph corresponding to a UTF-32 codepoint.
virtual bool LoadGlyph(uint codepoint, bool for_render) = 0;
/// Render currently loaded glyph to a picture.
virtual bool RenderCurrentGlyph(Picture &picture, const iPoint &position, const iRect &clip, const Color &color = Color::White) = 0;
/// Set a fallback font to query in case a glyph cannot be found in this font.
virtual void SetFallback(IFont *) {}
virtual ~IFont() {}
};
typedef SharedPtr <IFont> sIFont;
} // GS
#endif // __FONTINTERFACE__

View File

@ -0,0 +1,122 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __FONTRENDERER__
#define __FONTRENDERER__
#include "font/font_extended.h"
#include "font/font_cache.h"
#include "math/vector.h"
namespace GS {
class Picture;
struct SubString;
/// Text widget state structure.
class TextState
{
int size;
float tracking, ///< Text tracking (horizontal offset between two characters).
leading; ///< Text heading (vertical offset between lines).
public:
enum Format
{
Line = 0,
Paragraph,
Column
};
enum Alignment
{
Left = 0,
Right,
Center,
Justify
};
sFontEx font;
Color color;
Format format; ///< Text format.
Alignment alignment; ///< Text alignment.
int column_width; ///< Text column width.
int GetSize() const { return font.IsValid() ? (int)(size * font->size_multiplier) : size; }
float GetTracking() const { return font.IsValid() ? tracking + font->tracking_offset : tracking; }
float GetLeading() const { return font.IsValid() ? leading + font->leading_offset : leading; }
void SetSize(int s) { size = s; }
void SetTracking(float t) { tracking = t; }
void SetLeading(float l) { leading = l; }
TextState()
{
size = 16;
color = Color::Black;
format = Line;
alignment = Left;
column_width = 80;
tracking = 0;
leading = 0;
}
};
/*
@short Font renderer.
@author Emmanuel Julien (ejulien@nworks.fr)
*/
class FontRenderer
{
public:
enum CommandCode
{
CommandNone = 0,
CommandColor,
CommandFont,
CommandSize,
CommandParseError
};
static float default_text_tracking;
static float default_text_heading;
/// Renderer command.
struct Command
{
CommandCode code;
Vector4 vector;
sIFont font;
};
protected:
/// Check current string for a command.
static const char *CheckCommand(const char *string, Command &command);
/// Get the next sub-string from the current text buffer.
static const char *FetchSubString(const char *string, SubString &sstr, TextState &state, int max_width, int max_character);
/// Draw a substring to a picture.
static void DrawSubString(SubString &sub_string, Picture &output, TextState &state, const iRect &out_rect, const iRect &clip_rect, int justification);
public:
/// Format a string using a text state, return the required output rectangle.
static iRect Format(const char *text, const TextState &in_state, const iRect &out_rect);
/// Compose a string using a text state.
static iRect Compose(Picture &output, const char *text, const TextState &state, const iRect &out_rect, const iRect &clip_rect);
};
} // GS
#endif // __FONTRENDERER__

View File

@ -0,0 +1,184 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
------------------------------------------------------------------------------*/
#ifndef __NBOUNDINGBOX__
#define __NBOUNDINGBOX__
#include "math/matrix3.h"
namespace GS {
/*!
@short AABB.
@author Emmanuel Julien (ejulien@nworks.fr)
*/
class MinMax
{
protected:
enum
{
ClipNone = 0,
ClipRight = 1,
ClipLeft = 2,
ClipTop = 4,
ClipBottom = 8,
ClipFront = 16,
ClipBack = 32
};
/// Internal use.
uint cc_oc(const Vector4 &min, const Vector4 &max, const Vector4 &p) const
{
uint oc = ClipNone;
if (p.x > max.x) oc |= ClipRight;
else if (p.x < min.x) oc |= ClipLeft;
if (p.y > max.y) oc |= ClipTop;
else if (p.y < min.y) oc |= ClipBottom;
if (p.z > max.z) oc |= ClipBack;
else if (p.z < min.z) oc |= ClipFront;
return oc;
}
/// Internal use.
uint ss_oc(const Vector4 &p) const
{
uint oc = ClipNone;
oc |= p.x > 0 ? ClipRight : ClipLeft;
oc |= p.y > 0 ? ClipTop : ClipBottom;
oc |= p.z > 0 ? ClipBack : ClipFront;
return oc;
}
public:
Vector4 mn, mx;
/// Return the start of the interval on a given axis.
float GetMin(uint axis) const
{ return mn[axis]; }
/// Return the end of the interval on a given axis.
float GetMax(uint axis) const
{ return mx[axis]; }
/// Return whether the MinMax object overlap with another one.
bool TestAxisOverlap(const MinMax &b, uint axis) const
{ return (b.mn[axis] > mx[axis]) || (b.mx[axis] < mn[axis]) ? false : true; }
/// Intersect ray with this minmax.
bool IntersectRay(const Vector4 &o, const Vector4 &d, float &tmin, float &tmax);
/// Returns whether a line intersect with the MinMax.
bool ClassifyLine(const Vector4 &p, const Vector4 &d, Vector4 &i, Vector4 *n = 0) const;
/// Returns whether a segment intersect with the MinMax.
bool ClassifySegment(const Vector4 &p0, const Vector4 &p1, Vector4 &i, Vector4 *n = 0) const;
/// Return whether two MinMax overlap at a given time.
bool TestOverlap(const MinMax &b) const
{
if (mx.x < b.mn.x) return false;
if (mx.y < b.mn.y) return false;
if (mx.z < b.mn.z) return false;
if (b.mx.x < mn.x) return false;
if (b.mx.y < mn.y) return false;
if (b.mx.z < mn.z) return false;
return true;
}
/// Test position.
inline bool IsInside(const Vector4 &p) const
{ return (p.x < mn.x) || (p.y < mn.y) || (p.z < mn.z) || (p.x > mx.x) || (p.y > mx.y) || (p.z > mx.z) ? false : true; }
/// Grow the min~max boundaries to include another min~max structure.
void Grow(const MinMax &b)
{
mn = Vector4::Minimum(b.mn, mn);
mx = Vector4::Maximum(b.mx, mx);
}
/// Grow the min~max boundaries to include a vector.
void Grow(const Vector4 &p)
{
mn = Vector4::Minimum(p, mn);
mx = Vector4::Maximum(p, mx);
}
/// Get the min-max area.
float GetArea() const
{ return (mx.x - mn.x) * (mx.y - mn.y) * (mx.z - mn.z); }
/// Get the min-max center.
Vector4 GetCenter() const
{ return (mn + mx) * 0.5f; }
/// Set min-max.
void Set(const Vector4 &min, const Vector4 &max)
{ mn = min; mx = max; }
/// Set from position and size.
void SetFromPositionSize(const Vector4 &p, const Vector4 &s)
{
mn = p - s * 0.5f;
mx = p + s * 0.5f;
}
void Reset()
{ mn.Set(); mx.Set(); }
/*!
@name Serialization
@{
*/
bool FromMetaTag(NML::Tag &tag);
NML::Tag *AsMetaTag();
/// @}
MinMax() : mn(0, 0, 0), mx(0, 0, 0) {}
MinMax(const Vector4 &min, const Vector4 &max) : mn(min), mx(max) {}
};
/*!
@short Oriented bounding box.
@author Emmanuel Julien (ejulien@nworks.fr)
*/
struct OBB
{
Vector4 bb_position;
Vector4 bb_scale;
Matrix3 bb_rotation;
/// Compute the min/max of the OBB.
void ComputeMinMax(MinMax &minmax);
/*!
@short Transform OBB.
@warning Scaling is not supported.
*/
void Transform(const Matrix4 &mtx);
/// OBB from min~max.
static OBB FromMinMax(const MinMax &minmax)
{ return OBB((minmax.mn + minmax.mx) * 0.5f, minmax.mx - minmax.mn); }
bool FromMetaTag(NML::Tag &tag);
NML::Tag *AsMetaTag();
OBB(const MinMax &minmax)
{ *this = FromMinMax(minmax); }
OBB(const Vector4 &p, const Vector4 &s, const Matrix3 *m = 0)
{
bb_position = p;
bb_scale = s;
if (m)
bb_rotation = *m;
}
OBB() {}
};
} // GS
#endif // __NBOUNDINGBOX__

View File

@ -0,0 +1,171 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NCURVE__
#define __NCURVE__
#include "math/nmath.h"
#include "metafile/nml.h"
#include "reflection/nenum_string.h"
#include "container/narray_list.h"
#include "time/ntime_range.h"
#include "time/ntime.h"
namespace GS {
static const float DefaultCurveOptimizationThreshold = 0.05f;
/*
@short Curve control point.
@author Emmanuel Julien (ejulien@nworks.fr)
*/
struct CurvePoint
{
NPLACEMENT_NEW(Curve)
/// Curve control point shape.
enum Shape
{
Shape_None = 0,
Shape_Linear,
Shape_TCB,
Shape_Hermite,
Shape_Bezier,
Shape_Bezier2,
Shape_Step
};
Shape shape;
Time t;
float v,
tension, continuity, bias,
param[4]; //< TCB parameters.
CurvePoint(const Time &time, float value, Shape shp = Shape_Linear) : t(time), v(value), shape(shp)
{
tension = 0;
continuity = 0;
bias = 0;
param[0] = param[1] = param[2] = param[3] = 0;
}
CurvePoint() : t(0), v(0), shape(Shape_Linear)
{
tension = 0;
continuity = 0;
bias = 0;
param[0] = param[1] = param[2] = param[3] = 0;
}
};
/*!
@short Curve object.
@author Emmanuel Julien (ejulien@nworks.fr)
*/
class Curve
{
public:
NPLACEMENT_NEW(Curve)
enum LoopMode
{
Reset = 0, ///< Returns 0.
Constant, ///< Returns first/last knot value.
Repeat, ///< Warp evaluation time to a value inside curve range and evaluate.
Oscillate, ///< Ping-pong style evaluation.
OffsetAndRepeat ///< Same as repeat but the whole curve is offset with the last knot value.
};
static Reflection::Enum::Dict loop_mode_dict[];
protected:
ArrayList <CurvePoint *> points; ///< Curve knots.
uint Optimize(uint point_count, const CurvePoint *src, CurvePoint *dst, float threshold);
public:
/// Evaluate curve at a given time.
void Evaluate(Time t, float *value, LoopMode loop_mode = Constant, Time loop_start = Time::Inf, Time loop_end = Time::Inf) const;
/// Evaluate incoming tangent to the curve.
float Incoming(const CurvePoint *kf0, const CurvePoint *kf1, const CurvePoint *kf2) const;
/// Evaluate outgoing tangent to the curve.
float Outgoing(const CurvePoint *kf0, const CurvePoint *kf1, const CurvePoint *kfp) const;
/*!
@short Update a control point.
@note The time epsilon is considered on both side of the control
points time. If no point to update is found a new point is
inserted.
*/
void Update(const CurvePoint &, const Time &t_epsilon);
/// Insert a control point.
void Insert(const CurvePoint &);
/// Append a control point to the control point list.
void Append(const CurvePoint &);
/// Delete a curve control point from the channel.
void Delete(CurvePoint *);
/// Get curve time range, very fast.
TimeRange GetTimeRange() const;
/// Get curve value range, requires a full parsing of the knot list.
Range <float> GetValueRange() const;
/// Get curve range length in time.
Time GetDuration() const { return GetTimeRange().valueRange(); }
/// Optimize curve removing the less influential knots.
uint Optimize(float threshold = DefaultCurveOptimizationThreshold);
/// Return the curve control points as an array.
ArrayList <CurvePoint *> &GetPoints() { return points; }
/// Return the number of control point in curve.
uint GetPointCount() const { return points.GetCount(); }
/// Sort curve point array by time.
void Sort();
/*!
@short Set a control point content.
@Note This function does modify the internal ordering of the curve
keys in order to keep them time ordered.
Please use the Sort() function to make sure the curve can
still be correctly evaluated after a key time modification.
*/
void SetPoint(uint index, const CurvePoint &content) const;
/// Allocate a set of control points.
bool AllocatePoint(uint n);
/*!
@short Return the closest point on curve to a given time position.
The default behavior is to return the first point whose time is
greater than the query time.
*/
int GetPointIndex(const Time &time, bool t_greater_than = true) const;
void Clear();
virtual size_t MemoryFootPrint() const { return size_t(points.GetCount()) * sizeof(CurvePoint) + sizeof(Curve); }
bool FromMetaTag(NML::Tag &);
NML::Tag *AsMetaTag() const;
virtual ~Curve();
};
} // GS
#endif // __NCURVE__

View File

@ -0,0 +1,76 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NFRUSTRUM__
#define __NFRUSTRUM__
#include "geometry/plane.h"
class nMatrix4;
namespace GS {
struct Shape;
class MinMax;
/*!
@short Frustum.
@author Emmanuel Julien (ejulien@nworks.fr)
*/
class Frustum
{
public:
enum Visibility
{
Outside = 0,
Inside,
Clipped
};
enum VolumePlane
{
Top = 0,
Bottom,
Left,
Right,
Near,
Far
};
protected:
Vector4 vtx[8]; ///< Frustum vertices.
Plane plane[6]; ///< Frustum planes.
public:
inline const Vector4 *GetVertices() const { return vtx; }
/// Compute perspective frustum volume planes.
void SetPerspective(float fov, float near, float far, const Matrix4 *m = 0, float h_ar = 1, float v_ar = 1);
/// Compute orthographic frustum volume planes.
void SetOrthographic(float width, float height, float near, float far, const Matrix4 *m = 0, float h_ar = 1, float v_ar = 1);
/// Return the visibility flag of a vector set against this frustum.
Visibility ClassifySet(uint count, const Vector4 * const GSRESTRICT set, const float offset = 0) const;
/// Return the visibility flag of a frustum against this frustum.
Visibility ClassifyFrustrum(const Frustum &frustum) const;
/// Return the visibility flag of a sphere against this frustum.
Visibility ClassifySphere(const Vector4 &p, float r) const;
/// Return the visibility flag of a minmax against this frustum.
Visibility ClassifyMinMax(const MinMax &mm, const Matrix4 *m = 0) const;
/// Return the visibility flag of a shape against this frustum.
Visibility ClassifyShape(const Shape &s, const Matrix4 *m = 0) const;
};
} // GS
#endif // __NFRUSTRUM__

View File

@ -0,0 +1,103 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NGEOMETRICTOOLS__
#define __NGEOMETRICTOOLS__
#include "math/vector.h"
namespace GS {
namespace Geometric {
/// Compute 2d triangle area.
float TriArea2D(float x0, float y0, float x1, float y1, float x2, float y2);
/*!
@short Test intersection between a ray and a plane.
@param a Origin of the ray.
@param v Direction of the ray.
@param n Normal of the plane.
@param p A point on the plane.
@param t Output, the parametric 't' value of the point of
intersection.
@return False if the ray is embedded in or coplanar to the plane.
True otherwise.
*/
bool LineIntersectPlane(const Vector4 &a, const Vector4 &v, const Vector4 &n, const Vector4 &p, float &t);
/*!
@short Compute barycentric coordinates.
*/
void Barycentric(const Vector4 &a, const Vector4 &b, const Vector4 &c, const Vector4 &p, float &u, float &v, float &w);
/*!
@short Test intersection between a ray and a plane.
@param a Origin of the ray.
@param v Normalized direction of the ray.
@param c Center of the sphere.
@param r Radius of the sphere.
@param t Output, the parametric 't' value of the points of
intersection. t[0] is the closest point of
intersection to the origin of the ray.
@return False if no intersection.
*/
bool LineIntersectSphere(const Vector4 &a, const Vector4 &v, const Vector4 &c, float r, float t[2]);
/*!
@short Determine the closest points between two lines.
@param a First point on first line.
@param b Second point on first line.
@param u First point on second line.
@param v Second point on second line.
@param t Output, the parametric 't' values of the closest
points on each line. t[0] belongs to (a;b), t[1]
belongs to (u;v).
@return False if both lines are parallel.
*/
bool LineClosestPointToLine(const Vector4 &a, const Vector4 &b, const Vector4 &u, const Vector4 &v, float t[2]);
/*!
@short Determine the closest point to a line from a position in space.
@param a First point on line.
@param b Second point on line.
@param u Location.
@param i Output the closest point on line to u.
@return t Parametric position of i on the [a;b] segment.
If t < 0 or t > 1 then i lies outside the [a;b] segment.
*/
float LineClosestPoint(const Vector4 &a, const Vector4 &b, const Vector4 &u, Vector4 *p = 0);
/*!
@short Determine the closest point to a segment from a position in space.
@param a First point on segment.
@param b Second point on segment.
@param u Location.
@param i Output the closest point on segment to u.
@return t Parametric position of i on the [a;b] segment.
*/
float SegmentClosestPoint(const Vector4 &a, const Vector4 &b, const Vector4 &u, Vector4 *p = 0);
} // Geometric
} // GS
#endif // __NGEOMETRICTOOLS__

View File

@ -0,0 +1,55 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NPLANE__
#define __NPLANE__
#include "math/vector.h"
namespace GS {
/*!
@short Plane.
ax + by + cz + d = 0
@author Emmanuel Julien (ejulien@nworks.fr)
*/
class Plane
{
float d; ///< Distance to origin.
Vector4 p, n; ///< Point in plane and normal.
public:
/// Return plane normal.
inline const Vector4 &GetNormal() const
{ return n; }
/*!
@short Return point distance to plane.
Distance is signed, positive when the point is in front of the plane,
negative otherwise.
*/
inline float DistanceToPlane(const Vector4 &p) const
{ return p.Dot(n) + d; }
/// Set plane from point/normal and an optional transformation matrix.
void Set(const Vector4 *_p, const Vector4 &_n, const Matrix4 * = 0);
/// Set plane three vectors and an optional transformation matrix.
void Set(const Vector4 _p[3], const Matrix4 * = 0);
Plane();
Plane(const Vector4 &_p, const Vector4 &_n, const Matrix4 *_m = 0)
{ Set(&_p, _n, _m); }
};
} // GS
#endif // __NPLANE__

View File

@ -0,0 +1,112 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NRECT__
#define __NRECT__
#include "ntypes.h"
namespace GS {
namespace NML {
class File;
class Tag;
}
/*!
@short Point.
@author Emmanuel Julien (ejulien@nworks.fr)
*/
template <class T> struct Point
{
T x, y;
T operator [] (size_t n) const { return *(&x + n); }
void Set(T _x, T _y)
{ x = _x; y = _y; }
Point(T ux, T uy) : x(ux), y(uy) {}
Point() : x(0), y(0) {}
};
typedef Point <int> iPoint;
typedef Point <float> fPoint;
/*!
@short Rectangle.
@author Emmanuel Julien (ejulien@nworks.fr)
*/
template <class T> struct Rect
{
T sx, sy, ex, ey;
void SetWidth(T w) { ex = sx + w; }
void SetHeight(T h) { ey = sy + h; }
T GetWidth() const { return ex - sx; }
T GetHeight() const { return ey - sy; }
Rect <T> operator * (T v) const
{ return Rect <T> (sx * v, sy * v, ex * v, ey * v); }
Rect <T> operator / (T v) const
{ return Rect <T> (sx / v, sy / v, ex / v, ey / v); }
bool Inside(T x, T y) const
{ return (x > sx) && (y > sy) && (x < ex) && (y < ey); }
bool FitsInside(const Rect <T> &b) const
{ return (GetWidth() <= b.GetWidth()) && (GetHeight() <= b.GetHeight()); }
bool Intersect(const Rect <T> &b) const
{ return ((ex < b.sx) || (ey < b.sy) || (sx > b.ex) || (sy > b.ey)) ? false : true; }
Rect <T> Intersection(const Rect <T> &b) const
{
T _sx = Types::Max(sx, b.sx), _sy = Types::Max(sy, b.sy),
_ex = Types::Min(ex, b.ex), _ey = Types::Min(ey, b.ey);
T n_sx = Types::Min(_sx, _ex), n_sy = Types::Min(_sy, _ey),
n_ex = Types::Max(_sx, _ex), n_ey = Types::Max(_sy, _ey);
return Rect <T> (_sx = n_sx, _sy = n_sy, _ex = n_ex, _ey = n_ey);
}
Rect <T> Grow(T border) const
{ return Rect <T> (sx - border, sy - border, ex + border, ey + border); }
void Set(T usx, T usy, T uex, T uey)
{ sx = usx; sy = usy; ex = uex; ey = uey; }
void Set(T ux = 0, T uy = 0)
{ sx = ux; sy = uy; ex = ux; ey = uy; }
Rect <T> Offset(T x, T y) const
{ return Rect <T> (sx + x, sy + y, ex + x, ey + y); }
Rect <float> AsFloat() const
{ return Rect <float> (float(sx), float(sy), float(ex), float(ey)); }
Rect <int> AsInt() const
{ return Rect <int> (int(sx), int(sy), int(ex), int(ey)); }
NML::Tag *AsMetaTag(const char *id) const;
bool FromMetaTag(NML::Tag &);
static Rect <T> FromWidthHeight(T sx, T sy, T w, T h)
{ return Rect <T> (sx, sy, sx + w, sy + h); }
Rect(const Rect <T> &b) : sx(b.sx), sy(b.sy), ex(b.ex), ey(b.ey) {}
Rect(T usx, T usy, T uex, T uey) : sx(usx), sy(usy), ex(uex), ey(uey) {}
Rect(T usx, T usy) : sx(usx), ex(usx), sy(usy), ey(usy) {}
Rect() : sx(0), sy(0), ex(0), ey(0) {}
};
typedef Rect <int> iRect;
typedef Rect <float> fRect;
} // GS
#endif // __NRECT__

View File

@ -0,0 +1,59 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NSAT__
#define __NSAT__
#include <float.h>
namespace GS {
namespace SAT {
/// SAT overlap test results.
enum Overlap
{
Outside = 0,
Inside, // B inside A
Clipped
};
/// Helper function to test overlap on a given axis.
Overlap TestOverlap(const Vector4 &axis, int ca, const Vector4 *a, int cb, const Vector4 *b)
{
// A interval.
float a_mn = FLT_MAX, a_mx = -FLT_MAX;
for (int n = 0; n < ca; ++n)
{
float d = axis.Dot(a[n]);
if (d < a_mn) a_mn = d;
if (d > a_mx) a_mx = d;
}
// B interval.
float b_mn = FLT_MAX, b_mx = -FLT_MAX;
for (int n = 0; n < cb; ++n)
{
float d = axis.Dot(b[n]);
if (d < b_mn) b_mn = d;
if (d > b_mx) b_mx = d;
}
// Test overlap.
if ((a_mx < b_mn) || (a_mn > b_mx))
return Outside;
if ((b_mn > a_mn) && (b_mx < a_mx))
return Inside;
return Clipped;
}
} // SAT
} // GS
#endif // __NSAT__

View File

@ -0,0 +1,225 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NMATRIX3__
#define __NMATRIX3__
#include "math/vector.h"
namespace GS {
struct Quaternion;
class Matrix4;
/*!
@short 3x3 Matrix.
This matrix class is column major.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
class Matrix3
{
static Matrix3 static_identity;
public:
NPLACEMENT_NEW(Matrix)
/// The matrix values.
float m[3][3];
bool operator == (const Matrix3 &b) const
{
for (uint i = 0; i < 3; i++)
for (uint j = 0; j < 3; j++)
if (!Math::TestEqual(m[i][j], b.m[i][j]))
return false;
return true;
}
bool operator != (const Matrix3 &b) const
{
for (uint i = 0; i < 3; i++)
for (uint j = 0; j < 3; j++)
if (!Math::TestEqual(m[i][j], b.m[i][j]))
return true;
return false;
}
Matrix3 operator + (const Matrix3 &b) const
{
Matrix3 r;
for (uint j = 0; j < 3; j++)
for (uint i = 0; i < 3; i++)
r.m[i][j] = m[i][j] + b.m[i][j];
return r;
}
void operator += (const Matrix3 &b)
{ *this = *this + b; }
void operator *= (const float k)
{
for (uint j = 0; j < 3; j++)
for (uint i = 0; i < 3; i++)
m[i][j] *= k;
}
void operator /= (const float k)
{
for (uint j = 0; j < 3; j++)
for (uint i = 0; i < 3; i++)
m[i][j] /= k;
}
Matrix3 operator - (const Matrix3 &b) const
{
Matrix3 r;
for (uint j = 0; j < 3; j++)
for (uint i = 0; i < 3; i++)
r.m[i][j] = m[i][j] - b.m[i][j];
return r;
}
void operator -= (const Matrix3 &b)
{ *this = *this - b; }
Vector4 operator * (const Vector4 &v) const
{
Vector4 o;
o.x = v.x * m[0][0] + v.y * m[0][1] + v.z * m[0][2];
o.y = v.x * m[1][0] + v.y * m[1][1] + v.z * m[1][2];
o.z = v.x * m[2][0] + v.y * m[2][1] + v.z * m[2][2];
o.w = 1;
return o;
}
Matrix3 operator * (const Matrix3 &b) const
{
#define __M33M33(__I, __J) m[__I][0] * b.m[0][__J] + m[__I][1] * b.m[1][__J] + m[__I][2] * b.m[2][__J]
return Matrix3 (
__M33M33(0, 0), __M33M33(1, 0), __M33M33(2, 0),
__M33M33(0, 1), __M33M33(1, 1), __M33M33(2, 1),
__M33M33(0, 2), __M33M33(1, 2), __M33M33(2, 2)
);
}
Matrix3 operator * (const float v) const
{
Matrix3 r;
for (uint j = 0; j < 3; j++)
for (uint i = 0; i < 3; i++)
r.m[i][j] = m[i][j] * v;
return r;
}
void operator *= (const Matrix3 &b)
{ *this = (*this) * b; }
Matrix3 operator / (const float v) const
{
Matrix3 r;
for (uint j = 0; j < 3; j++)
for (uint i = 0; i < 3; i++)
r.m[i][j] = m[i][j] / v;
return r;
}
/// Apply to a set of vector objects.
void Apply(Vector4 *o, const Vector4 *v, uint n = 1) const;
/// Compute the determinant of the matrix.
float Det() const
{
return ((m[1][1] * m[2][2]) - (m[1][2] * m[2][1])) * m[0][0] +
((m[1][2] * m[2][0]) - (m[1][0] * m[2][2])) * m[0][1] +
((m[1][0] * m[2][1]) - (m[1][1] * m[2][0])) * m[0][2];
}
/// Compute inverse matrix.
bool Inverse(Matrix3 &i) const;
/// Return the transposed matrix.
inline Matrix3 Transposed() const
{
return Matrix3
(
m[0][0], m[0][1], m[0][2],
m[1][0], m[1][1], m[1][2],
m[2][0], m[2][1], m[2][2]
);
}
/// Return the nth row.
inline Vector4 GetRow(uint n) const { return Vector4(m[0][n], m[1][n], m[2][n]); }
/// Return the nth column.
inline Vector4 GetColumn(uint n) const { return Vector4(m[n][0], m[n][1], m[n][2]); }
/// Set the nth row.
void SetRow(uint n, const Vector4 &row);
/// Set the nth column.
void SetColumn(uint n, const Vector4 &col);
/// Set matrix values.
void Set (
float m00, float m10, float m20,
float m01, float m11, float m21,
float m02, float m12, float m22
);
/// Set matrix values.
void Set(const Vector4 &u, const Vector4 &v, const Vector4 &w);
/// Return this matrix after normalization.
Matrix3 Normalized() const;
/// Normalize as orthonormal base.
Matrix3 AsOrthonormalBase() const;
/// Return an Euler orientation equivalent to this matrix.
Vector4 AsEuler(Math::rOrder rorder = Math::rOrder_Default) const;
/// Vector matrix.
static Matrix3 VectorMatrix(const Vector4 &v);
/// Identity matrix.
static Matrix3 &IdentityMatrix() { return static_identity; }
/// Translation matrix.
static Matrix3 TranslationMatrix(const Vector2 &t);
static Matrix3 TranslationMatrix(const Vector4 &t);
/// Scale matrix.
static Matrix3 ScaleMatrix(const Vector2 &s);
static Matrix3 ScaleMatrix(const Vector4 &s);
/// Cross product matrix.
static Matrix3 CrossProductMatrix(const Vector4 &v);
/// Rotation matrix around X axis.
static Matrix3 RotationMatrixXAxis(float a);
/// Rotation matrix around Y axis.
static Matrix3 RotationMatrixYAxis(float a);
/// Rotation matrix around Z axis.
static Matrix3 RotationMatrixZAxis(float a);
/*!
@short From Orthonormal basis.
Transform an orthogonal basis formed by one or two vectors to a
rotation matrix.
@note Left-handed base, eg: u = {1,0,0}, v = {0,1,0}, w = {0,0,1}.
*/
static Matrix3 FromOrthonormalBasis(const Vector4 &w, const Vector4 *v = 0);
/// From Euler triplet.
static Matrix3 FromEuler(float x = 0, float y = 0, float z = 0, Math::rOrder rorder = Math::rOrder_Default);
/// From Euler vector.
static Matrix3 FromEuler(const Vector4 &euler, Math::rOrder rorder = Math::rOrder_Default);
/// From matrix4.
static Matrix3 FromMatrix4(const Matrix4 &mtx);
NML::Tag *AsMetaTag(const char *) const;
bool FromMetaTag(NML::Tag &);
Matrix3(
float m00 = 1, float m10 = 0, float m20 = 0,
float m01 = 0, float m11 = 1, float m21 = 0,
float m02 = 0, float m12 = 0, float m22 = 1
)
{ Set(m00, m10, m20, m01, m11, m21, m02, m12, m22); }
Matrix3(const Vector4 &u, const Vector4 &v, const Vector4 &w)
{ Set(u, v, w); }
};
} // GS
#endif // __NMATRIX3__

View File

@ -0,0 +1,239 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NMATRIX4__
#define __NMATRIX4__
#include "math/vector.h"
namespace GS {
class Matrix3;
/*!
@short 4x4 Matrix.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
class Matrix4
{
static Matrix4 static_identity;
public:
NPLACEMENT_NEW(Matrix)
/// The matrix values.
float m[4][4];
bool operator == (const Matrix4 &b) const
{
for (uint i = 0; i < 4; i++)
for (uint j = 0; j < 4; j++)
if (!Math::TestEqual(m[i][j], b.m[i][j]))
return false;
return true;
}
bool operator != (const Matrix4 &b) const
{
for (uint i = 0; i < 4; i++)
for (uint j = 0; j < 4; j++)
if (!Math::TestEqual(m[i][j], b.m[i][j]))
return true;
return false;
}
inline Matrix4 operator * (const Matrix4 &b) const
{
#define __M44M44(__I, __J) m[__I][0] * b.m[0][__J] + m[__I][1] * b.m[1][__J] + m[__I][2] * b.m[2][__J] + m[__I][3] * b.m[3][__J]
return Matrix4(
__M44M44(0, 0), __M44M44(1, 0), __M44M44(2, 0), __M44M44(3, 0),
__M44M44(0, 1), __M44M44(1, 1), __M44M44(2, 1), __M44M44(3, 1),
__M44M44(0, 2), __M44M44(1, 2), __M44M44(2, 2), __M44M44(3, 2),
__M44M44(0, 3), __M44M44(1, 3), __M44M44(2, 3), __M44M44(3, 3)
);
}
const Matrix4 operator * (float v) const
{
Matrix4 r;
for (uint j = 0; j < 4; ++j)
for (uint i = 0; i < 4; ++i)
r.m[i][j] = m[i][j] * v;
return r;
}
const Matrix4 operator + (const Matrix4 &b) const
{
Matrix4 r;
for (uint j = 0; j < 4; j++)
for (uint i = 0; i < 4; i++)
r.m[i][j] = m[i][j] + b.m[i][j];
return r;
}
/// Return the nth row.
inline Vector4 GetRow(uint n, bool w_to_one = true) const
{ return Vector4(m[0][n], m[1][n], m[2][n], w_to_one ? 1 : m[3][n]); }
/// Return the nth column.
inline Vector4 GetColumn(uint n, bool w_to_one = true) const
{ return Vector4(m[n][0], m[n][1], m[n][2], w_to_one ? 1 : m[n][3]); }
/// Set the nth row.
inline void SetRow(uint n, const Vector4 &r, bool w_to_one = true)
{ m[0][n] = r.x; m[1][n] = r.y; m[2][n] = r.z; m[3][n] = w_to_one ? 1 : r.w; }
/// Set the nth column.
inline void SetColumn(uint n, const Vector4 &c, bool w_to_one = true)
{ m[n][0] = c.x; m[n][1] = c.y; m[n][2] = c.z; m[n][3] = w_to_one ? 1 : c.w; }
bool Inverse(Matrix4 &out) const;
/*!
@short Return the inverse matrix using a fast approximation.
@warning This function works only for standard 3d transformation
matrices.
*/
Matrix4 InversedFast() const;
/// Transpose matrix.
Matrix4 Transposed() const
{
return Matrix4(
m[0][0], m[0][1], m[0][2], m[0][3],
m[1][0], m[1][1], m[1][2], m[1][3],
m[2][0], m[2][1], m[2][2], m[2][3],
m[3][0], m[3][1], m[3][2], m[3][3]
);
}
/// Normalize matrix.
Matrix4 AsOrthonormalBase() const;
/// Interpolate between two 4x4 transformation matrices.
static Matrix4 LerpAsOrthonormalBase(const Matrix4 &a, const Matrix4 &b, float k, bool fast = false);
/// Decompose a transformation matrix into a position vector, a scale vector and a 3x3 rotation matrix.
void Decompose(Vector4 *position, Vector4 *scale = 0, Matrix3 *rotation = 0) const;
/// Decompose a transformation matrix into a position vector, a scale vector and a rotation vector.
void Decompose(Vector4 *position, Vector4 *scale, Vector4 *rotation, Math::rOrder order = Math::rOrder_Default) const;
/// Apply to vector array.
inline void Apply(Vector4 *o, const Vector4 *i, uint n = 1) const
{
for (uint c = 0; c < n; c++)
{
o[c].x = i[c].x * m[0][0] + i[c].y * m[0][1] + i[c].z * m[0][2] + i[c].w * m[0][3];
o[c].y = i[c].x * m[1][0] + i[c].y * m[1][1] + i[c].z * m[1][2] + i[c].w * m[1][3];
o[c].z = i[c].x * m[2][0] + i[c].y * m[2][1] + i[c].z * m[2][2] + i[c].w * m[2][3];
o[c].w = i[c].x * m[3][0] + i[c].y * m[3][1] + i[c].z * m[3][2] + i[c].w * m[3][3];
}
}
/// Apply upper-left 3x3 sub-matrix to vector array.
inline void ApplyRotation(Vector4 *o, const Vector4 *i, uint n = 1) const
{
for (uint c = 0; c < n; c++)
{
o[c].x = i[c].x * m[0][0] + i[c].y * m[0][1] + i[c].z * m[0][2];
o[c].y = i[c].x * m[1][0] + i[c].y * m[1][1] + i[c].z * m[1][2];
o[c].z = i[c].x * m[2][0] + i[c].y * m[2][1] + i[c].z * m[2][2];
o[c].w = 1.f;
}
}
/// Set values.
void Set (
float m00, float m10, float m20, float m30,
float m01, float m11, float m21, float m31,
float m02, float m12, float m22, float m32,
float m03, float m13, float m23, float m33
)
{
m[0][0] = m00; m[1][0] = m10; m[2][0] = m20; m[3][0] = m30;
m[0][1] = m01; m[1][1] = m11; m[2][1] = m21; m[3][1] = m31;
m[0][2] = m02; m[1][2] = m12; m[2][2] = m22; m[3][2] = m32;
m[0][3] = m03; m[1][3] = m13; m[2][3] = m23; m[3][3] = m33;
}
/// Identity matrix.
static const Matrix4 &IdentityMatrix()
{ return static_identity; }
/// Translation matrix.
static Matrix4 TranslationMatrix(const Vector4 &t);
/// Scale matrix.
static Matrix4 ScaleMatrix(const Vector4 &s);
/// From matrix3.
static Matrix4 FromMatrix3(const Matrix3 &mtx);
/// Position/scale/rotation/offset matrix.
static Matrix4 TransformationMatrix(const Vector4 &p, const Vector4 &r, const Vector4 &s, const Vector4 *o = 0);
/// Position/scale/rotation/offset matrix.
static Matrix4 TransformationMatrix(const Vector4 &p, const Matrix3 &r, const Vector4 &s, const Vector4 *o = 0);
NML::Tag *AsMetaTag(const char *id) const;
bool FromMetaTag(NML::Tag &);
Matrix4(
float m00, float m10, float m20, float m30,
float m01, float m11, float m21, float m31,
float m02, float m12, float m22, float m32,
float m03, float m13, float m23, float m33
)
{
m[0][0] = m00; m[1][0] = m10; m[2][0] = m20; m[3][0] = m30;
m[0][1] = m01; m[1][1] = m11; m[2][1] = m21; m[3][1] = m31;
m[0][2] = m02; m[1][2] = m12; m[2][2] = m22; m[3][2] = m32;
m[0][3] = m03; m[1][3] = m13; m[2][3] = m23; m[3][3] = m33;
}
Matrix4() {}
};
/*
@short 4x4 matrix with inverse.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
class Matrix4WithInverse
{
protected:
NPLACEMENT_NEW(Matrix)
Matrix4 matrix,
imatrix;
/// Commit a matrix change.
void Commit();
public:
/// Return the matrix inverse.
const Matrix4 &Get() const;
/// Return the matrix inverse.
const Matrix4 &GetInverse() const;
/// Set matrix.
void Set(const Matrix4 &m);
/// Return the nth row.
Vector4 GetRow(uint n, bool w_1 = true) const;
/// Return the nth column.
Vector4 GetColumn(uint n, bool w_1 = true) const;
/// Set the nth row.
void SetRow(uint n, const Vector4 &row, bool w_1 = true);
/// Set the nth column.
void SetColumn(uint n, const Vector4 &col, bool w_1 = true);
bool FromMetaTag(NML::Tag &tag);
NML::Tag *AsMetaTag(const char *id) const;
Matrix4WithInverse()
{
matrix = Matrix4::IdentityMatrix();
imatrix = Matrix4::IdentityMatrix();
}
};
} // GS
#endif // __NMATRIX4__

View File

@ -0,0 +1,107 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NQUATERNION__
#define __NQUATERNION__
#include "math/nmath.h"
namespace GS {
struct Vector4;
class Matrix3;
namespace NML {
class File;
class Tag;
}
/*!
@short Quaternion.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
struct Quaternion
{
float x, y, z, w;
void operator += (const Quaternion &b) { x += b.x; y += b.y; z += b.z; w += b.w; };
void operator += (float k) { x += k; y += k; z += k; w += k; };
void operator -= (const Quaternion &b) { x -= b.x; y -= b.y; z -= b.z; w -= b.w; };
void operator -= (float k) { x -= k; y -= k; z -= k; w -= k; };
void operator *= (const Quaternion &b)
{
Quaternion t = *this;
w = t.w * b.w - (t.x * b.x + t.y * b.y + t.z * b.z);
x = t.w * b.x + b.w * t.x + t.y * b.z - t.z * b.y;
y = t.w * b.y + b.w * t.y + t.z * b.x - t.x * b.z;
z = t.w * b.z + b.w * t.z + t.x * b.y - t.y * b.x;
};
void operator *= (float k) { x *= k; y *= k; z *= k; w *= k; };
void operator /= (float k) { k = 1.f / k; x *= k; y *= k; z *= k; w *= k; };
Quaternion operator + (const Quaternion &b) const
{ return Quaternion(x + b.x, y + b.y, z + b.z, w + b.w); }
Quaternion operator + (float v) const
{ return Quaternion(x + v, y + v, z + v, w + v); }
Quaternion operator - (const Quaternion &b) const
{ return Quaternion(x - b.x, y - b.y, z - b.z, w - b.w); }
Quaternion operator - (float v) const
{ return Quaternion(x - v, y - v, z - v, w - v); }
Quaternion operator * (const Quaternion &b) const
{
return Quaternion (
w * b.x + b.w * x + y * b.z - z * b.y,
w * b.y + b.w * y + z * b.x - x * b.z,
w * b.z + b.w * z + x * b.y - y * b.x,
w * b.w - (x * b.x + y * b.y + z * b.z)
);
}
Quaternion operator * (float v) const
{ return Quaternion(x * v, y * v, z * v, w * v); }
Quaternion operator / (float v) const
{ v = 1.f / v; return Quaternion(x * v, y * v, z * v, w * v); }
/// Dot product.
float Dot(const Quaternion &b) const
{ return x * b.x + y * b.y + z * b.z + w * b.w; }
/// Normalize quaternion.
Quaternion Normalize() const;
/// Inverse quaternion.
Quaternion Inverse() const;
/// To rotation matrix.
Matrix3 AsMatrix3() const;
/// Distance to quaternion.
static float Distance(const Quaternion &a, const Quaternion &b);
/// Slerp.
static Quaternion Slerp(float t, const Quaternion &a, const Quaternion &b);
/// From Euler angle.
static Quaternion FromEuler(float x, float y, float z, Math::rOrder rorder = Math::rOrder_Default);
/// Get an orientation from a 'look at' vector (look_at = to - from).
static Quaternion LookAt(const Vector4 &at);
/// From matrix3.
static Quaternion FromMatrix3(const Matrix3 &m);
/// From axis-angle.
static Quaternion FromAxisAngle(float angle, float x, float y, float z);
/// Set quaternion values.
void Set(float _x = 0, float _y = 0, float _z = 0, float _w = 1.f)
{ x = _x; y = _y; z = _z; w = _w; }
NML::Tag *AsMetaTag(const char *id) const;
bool FromMetaTag(NML::Tag &tag);
Quaternion(float _x = 0, float _y = 0, float _z = 0, float _w = 1.f)
{ Set(_x, _y, _z, _w); }
};
} // GS
#endif // __NQUATERNION__

View File

@ -0,0 +1,301 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NVECTOR__
#define __NVECTOR__
#include "math/nmath.h"
#include "alloc/ialloc.h"
namespace GS {
class Matrix3;
class Matrix4;
namespace NML {
class File;
class Tag;
}
/*!
@short Vector 2d template class.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
template <class T> struct tVector2
{
NPLACEMENT_NEW(Vector)
T x, y;
inline bool operator == (const tVector2 <T> &b) const { return (x == b.x) && (y == b.y); }
inline bool operator != (const tVector2 <T> &b) const { return (x != b.x) || (y != b.y); }
inline void operator += (const tVector2 <T> &b) { x += b.x; y += b.y; }
inline void operator += (const float k) { x += k; y += k; }
inline void operator -= (const tVector2 <T> &b) { x -= b.x; y -= b.y; }
inline void operator -= (const float k) { x -= k; y -= k; }
inline void operator *= (const tVector2 <T> &b) { x *= b.x; y *= b.y; }
inline void operator *= (const float k) { x *= k; y *= k; }
inline void operator /= (const tVector2 <T> &b) { x /= b.x; y /= b.y; }
inline void operator /= (const float k) { x /= k; y /= k; }
inline tVector2 <T> operator + (const tVector2 <T> &b) const { return tVector2 <T> (x + b.x, y + b.y); }
inline tVector2 <T> operator + (const T v) const { return tVector2 <T> (x + v, y + v); }
inline tVector2 <T> operator - (const tVector2 <T> &b) const { return tVector2 <T> (x - b.x, y - b.y); }
inline tVector2 <T> operator - (const T v) const { return tVector2 <T> (x - v, y - v); }
inline tVector2 <T> operator * (const tVector2 <T> &b) const { return tVector2 <T> (x * b.x, y * b.y); }
inline tVector2 <T> operator * (const T v) const { return tVector2 <T> (x * v, y * v); }
inline tVector2 <T> operator / (const tVector2 <T> &b) const { return tVector2 <T> (x / b.x, y / b.y); }
inline tVector2 <T> operator / (const T v) const { return tVector2 <T> (x / v, y / v); }
tVector2 <T> operator * (const Matrix3 &m) const;
/// Squared vector length.
inline float Len2() const { return (float)(x * x + y * y); }
/// Vector length.
inline float Len() const { return Math::Sqrt((float)(x * x + y * y)); }
/// Normalize this vector.
inline void Normalize() { float l = Len(); if (l) { float k = 1.f / l; x *= k; y *= k; } }
/// Normalize vector.
inline tVector2 <T> Normalized() const
{
float k = 1.f / Len();
return tVector2 <T>(x * k, y * k);
}
/// Reversed vector.
inline tVector2 <T> Reversed() const
{ return tVector2 <T> (-x, -y); }
/// Vector squared distance.
static float Dist2(const tVector2 &a, const tVector2 &b)
{ return ((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y)); }
/// Vector distance.
static float Dist(const tVector2 &a, const tVector2 &b)
{ return Math::Sqrt((float)((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y))); }
/// Set vector 2D components.
inline void Set(const T a, const T b) { x = a; y = b; }
tVector2 <T> (T a, T b) { Set(a, b); }
tVector2 <T> () { Set(0, 0); }
};
typedef tVector2 <float> Vector2;
/*!
@short 4-Component vector
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
struct Vector4
{
NPLACEMENT_NEW(Vector)
float x, y, z, w;
inline bool operator == (const Vector4 &b) const { return Math::TestEqual(x, b.x) && Math::TestEqual(y, b.y) && Math::TestEqual(z, b.z); }
inline bool operator != (const Vector4 &b) const { return !Math::TestEqual(x, b.x) || !Math::TestEqual(y, b.y) || !Math::TestEqual(z, b.z); }
inline void operator += (const Vector4 &b) { x += b.x; y += b.y; z += b.z; };
inline void operator += (const float k) { x += k; y += k; z += k; };
inline void operator -= (const Vector4 &b) { x -= b.x; y -= b.y; z -= b.z; };
inline void operator -= (const float k) { x -= k; y -= k; z -= k; };
inline void operator *= (const Vector4 &b) { x *= b.x; y *= b.y; z *= b.z; };
inline void operator *= (const float k) { x *= k; y *= k; z *= k; };
inline void operator /= (const Vector4 &b) { x /= b.x; y /= b.y; z /= b.z; };
inline void operator /= (const float k) { float k_ = k ? 1 / k : 0; x *= k_; y *= k_; z *= k_; };
inline Vector4 operator + (const Vector4 &b) const { return Vector4(x + b.x, y + b.y, z + b.z); }
inline Vector4 operator + (const float v) const { return Vector4(x + v, y + v, z + v); }
inline Vector4 operator - (const Vector4 &b) const { return Vector4(x - b.x, y - b.y, z - b.z); }
inline Vector4 operator - (const float v) const { return Vector4(x - v, y - v, z - v); }
inline Vector4 operator * (const Vector4 &b) const { return Vector4(x * b.x, y * b.y, z * b.z); }
inline Vector4 operator * (const float v) const { return Vector4(x * v, y * v, z * v); }
inline Vector4 operator / (const Vector4 &b) const { return Vector4(x / b.x, y / b.y, z / b.z); }
inline Vector4 operator / (const float v) const { float i = v ? 1 / v : 0; return Vector4(x * i, y * i, z * i); }
inline float operator [] (size_t n) const { return (&x)[n]; }
inline float &operator [] (size_t n) { return (&x)[n]; }
inline Vector4 SafeDivided(const Vector4 &b) const
{ return Vector4(b.x ? x / b.x : 0, b.y ? y / b.y : 0, b.z ? z / b.z : 0); }
/// Set vector components.
inline void Set(float x_, float y_, float z_, float w_)
{ x = x_; y = y_; z = z_; w = w_; }
inline void Set(float x_ = 0.f, float y_ = 0.f, float z_ = 0.f) // Used to provide script overload.
{ x = x_; y = y_; z = z_; w = 1.0f; }
inline void Set(Vector4 &v)
{ x = v.x; y = v.y; z = v.z; w = v.w; }
/// Dot product.
inline float Dot(const Vector4 &b) const
{ return x * b.x + y * b.y + z * b.z; }
/// Cross product.
inline Vector4 Cross(const Vector4 &b) const
{ return Vector4(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x); }
void operator *= (const Matrix4 &);
Vector4 operator * (const Matrix4 &) const;
void operator *= (const Matrix3 &);
Vector4 operator * (const Matrix3 &) const;
/// Reverse this vector.
inline void Reverse() { x = -x; y = -y; z = -z; }
/// Inverse vector.
inline void Inverse() { x = x ? 1.f / x : 0; y = y ? 1.f / y : 0; z = z ? 1.f / z : 0; }
/// Normalize this vector.
inline void Normalize() { float l = Len(); if (l) { float k = 1.f / l; x *= k; y *= k; z *= k; } }
/// Normalize vector.
inline Vector4 Normalized() const
{
float l = Len();
float k = l ? 1.f / l : 1.f;
return Vector4(x * k, y * k, z * k);
}
/// Clamp vector components to [min;max].
Vector4 Clamped(float min, float max) const;
/// Clamp vector components to [min;max].
Vector4 Clamped(const Vector4 &min, const Vector4 &max) const;
/// Clamp vector magnitude to [min;max].
Vector4 ClampedMagnitude(float min, float max) const;
/// Return the opposite vector to this vector.
inline Vector4 Reversed() const
{ return Vector4(-x, -y, -z); }
/// Return the inverse vector to this vector.
inline Vector4 Inversed() const
{ return Vector4(1.f / x, 1.f / y, 1.f / z); }
/// Absolute vector.
Vector4 Abs() const;
/// Sign vector.
inline Vector4 Sign() const
{ return Vector4(x < 0.f ? -1.f : 1.f, y < 0.f ? -1.f : 1.f, z < 0.f ? -1.f : 1.f); }
/// Maximum of two vectors.
static Vector4 Maximum(const Vector4 &a, const Vector4 &b)
{ return Vector4(a.x > b.x ? a.x : b.x, a.y > b.y ? a.y : b.y, a.z > b.z ? a.z : b.z); }
/// Minimum of two vectors.
static Vector4 Minimum(const Vector4 &a, const Vector4 &b)
{ return Vector4(a.x < b.x ? a.x : b.x, a.y < b.y ? a.y : b.y, a.z < b.z ? a.z : b.z); }
/*!
@short Reflect vector.
@note Vector must be normalized.
*/
inline Vector4 Reflected(const Vector4 &n) const
{
Vector4 rv = Reversed();
return n * (2.f * rv.Dot(n)) - rv;
}
/*!
@short Refract vector.
@note Vector must be normalized.
*/
inline Vector4 Refracted(const Vector4 &n, float kin = 1, float kout = 1) const
{
const float k = kin / kout;
return (*this) * k + n * (k - 1.f);
}
/// Squared vector length.
inline float Len2() const { return (float)(x * x + y * y + z * z); }
/// Vector length.
inline float Len() const { return Math::Sqrt((float)(x * x + y * y + z * z)); }
/// Hash vector.
int Hash() const;
Vector4 Floor() const;
Vector4 Ceil() const;
/*!
@short Return a random vector.
@note w component is not randomized but set to 1.
*/
static Vector4 Random(float min = -1, float max = 1);
/// Vector squared distance.
static float Dist2(const Vector4 &a, const Vector4 &b)
{ return ((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y) + (b.z - a.z) * (b.z - a.z)); }
/// Vector distance.
static float Dist(const Vector4 &a, const Vector4 &b)
{ return Math::Sqrt((float)((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y) + (b.z - a.z) * (b.z - a.z))); }
/*!
@short Vector base to Euler.
@note base convention u = {0,0,1}, v = {1,0,0}, second axis is optional.
*/
static void BaseToEuler(Vector4 &euler, Vector4 &u, Vector4 *v = NULL);
/*!
@short Return a vector which is facing a given direction.
Returns a copy of this vector if it is already facing the given
direction or the opposite of this vector otherwise.
*/
Vector4 FaceForward(Vector4 &dir);
NML::Tag *AsMetaTag(const char *id, bool full_dump = false) const;
bool FromMetaTag(NML::Tag &tag);
Vector4(float a, float b, float c, float d = 1) : x(a), y(b), z(c), w(d) {}
Vector4(const tVector2 <float> &v2) : x(v2.x), y(v2.y), z(1), w(1) {}
Vector4(const tVector2 <int> &v2) : x(float(v2.x)), y(float(v2.y)), z(1), w(1) {}
Vector4() {}
};
} // GS
#define Vec3Set(v, a, b, c) { (v).x = a; (v).y = b; (v).z = c; }
#define Vec3Len2(v) ((v).x * (v).x + (v).y * (v).y + (v).z * (v).z)
#define Vec3Len(v) Math::Sqrt((float)Vec3Len2(v))
#define Vec3Add(r, a, b) { (r).x = (a).x + (b).x; (r).y = (a).y + (b).y; (r).z = (a).z + (b).z; }
#define Vec3AddConst(r, a, k) { (r).x = (a).x + k; (r).y = (a).y + k; (r).z = (a).z + k; }
#define Vec3Sub(r, a, b) { (r).x = (a).x - (b).x; (r).y = (a).y - (b).y; (r).z = (a).z - (b).z; }
#define Vec3SubConst(r, a, k) { (r).x = (a).x - k; (r).y = (a).y - k; (r).z = (a).z - k; }
#define Vec3Mul(r, a, b) { (r).x = (a).x * (b).x; (r).y = (a).y * (b).y; (r).z = (a).z * (b).z; }
#define Vec3MulConst(r, a, k) { float _k = k; (r).x = (a).x * _k; (r).y = (a).y * _k; (r).z = (a).z * _k; }
#define Vec3Div(r, a, b) { (r).x = (a).x / (b).x; (r).y = (a).y / (b).y; (r).z = (a).z / (b).z; }
#define Vec3DivConst(r, a, k) { float ik = 1.f / k; (r).x = (a).x * ik; (r).y = (a).y * ik; (r).z = (a).z * ik; }
#define Vec3Inc(r, a) { (r).x += (a).x; (r).y += (a).y; (r).z += (a).z; }
#define Vec3IncConst(r, k) { (r).x += k; (r).y += k; (r).z += k; }
#define Vec3Dec(r, a) { (r).x -= (a).x; (r).y -= (a).y; (r).z -= (a).z; }
#define Vec3DecConst(r, k) { (r).x -= k; (r).y -= k; (r).z -= k; }
#define Vec3Scale(r, a) { (r).x *= (a).x; (r).y *= (a).y; (r).z *= (a).z; }
#define Vec3ScaleConst(r, k) { float _k = k; (r).x *= _k; (r).y *= _k; (r).z *= _k; }
#define Vec3Shrink(r, a) { (r).x /= (a).x; (r).y /= (a).y; (r).z /= (a).z; }
#define Vec3ShrinkConst(r, k) { float ik = 1.f / k; (r).x *= ik; (r).y *= ik; (r).z *= ik; }
#define Vec3Dot(a, b) ((a).x * (b).x + (a).y * (b).y + (a).z * (b).z)
#define Vec3Cross(r, a, b) {\
(r).x = (a).y * (b).z - (a).z * (b).y;\
(r).y = (a).z * (b).x - (a).x * (b).z;\
(r).z = (a).x * (b).y - (a).y * (b).x;\
}
#define Vec3Clamp(v, a, b) {\
if ((v).x < a) (v).x = a; else if ((v).x > b) (v).x = b;\
if ((v).x < a) (v).x = a; else if ((v).x > b) (v).x = b;\
if ((v).x < a) (v).x = a; else if ((v).x > b) (v).x = b;\
}
#define Vec3ClampMag(v, m) {\
const float m2 = (m) * (m);\
const float l2 = Vec3Len2(v);\
if (l2 > m2)\
{\
const float k = Math::Sqrt((float)(m2 / l2));\
Vec3ScaleConst(v, k);\
}\
}
#endif // __NVECTOR__

View File

@ -0,0 +1,50 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NVECTORNML__
#define __NVECTORNML__
#include "metafile/nml.h"
#include "math/vector.h"
namespace GS {
//------------------------------------------------------------------------------
template <class T> NML::Tag *tVectorAsMetaTag(const tVector2 <T> &v, const char *id)
{
NML::Tag *root = id ? new NML::Tag(id) : new NML::Tag("Vector2");
if (root)
{
root->AddChild("X", v.x);
root->AddChild("Y", v.y);
}
return root;
}
template <class T> bool tVectorFromMetaTag(tVector2 <T> &v, NML::Tag &tag)
{
NML::Tag *t;
List <NML::Tag *> ::Iterator i(tag.GetTags().GetRoot());
if ((t = i.ObjectPtr()) == NULL)
return false;
v.x = t->GetReal();
++i;
if ((t = i.ObjectPtr()) == NULL)
return false;
v.y = t->GetReal();
return true;
}
//------------------------------------------------------------------------------
} // GS
#endif // __NVECTORNML__

View File

@ -0,0 +1,224 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NMETALANG__
#define __NMETALANG__
#include "data/nvariant.h"
#include "container/nlist.h"
namespace GS {
namespace IO { class Handle; }
namespace NML {
class Tag;
class File;
static const int version = 1;
/// Metatag.
class Tag
{
friend struct Parser;
friend class File;
protected:
/// Locate a tag through its path.
static Tag *GetTagEx(const List <Tag *> &tag, const char *path, const File *root = 0, bool verbose = false);
List <Tag *> tags;
Variant value;
public:
NPLACEMENT_NEW(Metatag)
String name;
/// Get this tag parent by exploring a given tag hierarchy.
Tag *GetParent(Tag *) const;
/// Get value.
Variant &GetValue() { return value; }
const Variant &GetValue() const { return value; }
/// Remove a child tag from this tag.
bool RemoveTag(Tag *t) { return tags.Remove(t); }
/// Delete all child tags.
uint DeleteChildren(const char *filter = 0);
/// Get child count.
uint GetChildCount() const { return tags.GetCount(); }
/// Return the tag children list.
const List <Tag *> &GetTags() const { return tags; }
/// Add child to tag.
Tag *AddChild(Tag *);
Tag *AddChild(const char *);
Tag *AddChild(const char *, bool);
Tag *AddChild(const char *, int);
Tag *AddChild(const char *, uint);
Tag *AddChild(const char *, float);
Tag *AddChild(const char *, const char *);
Tag *AddChild(const char *, void *, size_t);
/// Return tag child.
Tag *GetTag(const char *path, const File * = 0, bool verbose = false) const;
/// Return the tag at a given path only if it matches the required type.
Tag *GetTypedTag(const char *path, Variant::Type, const File * = 0, bool verbose = false) const;
bool GetBool() const { bool v; if (value.Get(v)) return v; return false; }
int GetInteger() const { return value.i_value; }
uint GetUnsigned() const { return value.u_value; }
const char *GetString() const { return value.s_value; }
float GetReal() const { return value.f_value; }
void SetBool(bool v) { value = v; }
void SetInteger(int v) { value = v; }
void SetUnsigned(uint v) { value = v; }
void SetString(const char *v) { value = v; }
void SetReal(float v) { value = v; }
Variant::Type GetType() const { return value.GetType(); }
/// Clone a tag and optionally recurse and clone its children.
bool Clone(const Tag &src, bool recursive = true);
/// Clone this tag and optionally recurse and clone its children.
Tag *Clone(bool recursive = true) const;
/// Free the tag data, set its type to nVariant::VariantNone.
void Free();
Tag() {}
Tag(const char *n) : name(n) {}
Tag(const char *n, bool v) : name(n), value(v) {}
Tag(const char *n, int v) : name(n), value(v) {}
Tag(const char *n, uint v) : name(n), value(v) {}
Tag(const char *n, float v) : name(n), value(v) {}
Tag(const char *n, const char *v) : name(n), value(v) {}
Tag(const char *n, void *data, size_t size) : name(n), value(data, size) {}
~Tag();
};
/*!
@short Meta file.
A metafile contain the whole database in memory.
This class is not meant to be used with heavy databases.
Tags can be accessed using tag paths. A tag path is formatted as follow:
"root:node:...:tag;".
@note The closing hyphen is not required but warnings will be sent to the
log if you don't use it. The node delimiter ':' can be repeated any
number of time between nodes with no effect (eg: ":::node1::node2:;").
By definition a file is a node tag and cannot have a value.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
class File
{
friend struct Parser;
public:
enum Binary
{
Binary_UU = 0, ///< UUEncoded.
Binary_yEnc ///< yEncoded.
};
protected:
List <Tag *> tags;
Binary binary_method; ///< Binary encoding method.
public:
String name;
/// Get the file ASCII binary encoding method.
Binary GetBinaryMethod() const { return binary_method; }
const List <Tag *> &GetTags() const { return tags; }
uint GetRootCount() const { return tags.GetCount(); }
void Clear() { ListDeleteAllPtr(Tag *, tags); }
bool isEmpty() const { return asbool(GetRootCount() == 0); }
/// Add a root tag to the file.
Tag *AddRoot(Tag *);
Tag *AddRoot(const char *);
Tag *AddRoot(const char *, bool);
Tag *AddRoot(const char *, int);
Tag *AddRoot(const char *, float);
Tag *AddRoot(const char *, const char *);
Tag *AddRoot(const char *, void *, size_t);
/// Unlink a root tag from file.
bool UnlinkRoot(Tag *);
/// Return the tag at a given path.
Tag *GetTag(const char *path, bool verbose = false) const
{ return Tag::GetTagEx(tags, path, this, verbose); }
/// Return the tag at a given path only if it match the required type.
Tag *GetTypedTag(const char *path, Variant::Type, bool verbose = false) const;
bool GetBool(const char *path, bool _default = false, bool verbose = false) const;
int GetInteger(const char *path, int _default = -1, bool verbose = false) const;
float GetReal(const char *path, float _default = -1.f, bool verbose = false) const;
const char *GetString(const char *path, const char *_default = 0, bool verbose = false) const;
/// Duplicate the structure of a source file into this file.
void Import(const File &, bool clear_before_import = true);
/// Clone a file and all its tags.
File *Clone() const;
void Free();
File() : binary_method(Binary_yEnc) {}
~File();
};
/*!
@short Meta file parser.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
struct Parser
{
static const char *ParseTagPreprocessorDirective(Tag &tag, const char *s, const char *e);
static bool IsMetafile(const char *);
static bool SaveBinaryTag(IO::Handle &, const Tag &, File::Binary = File::Binary_yEnc);
static bool SaveTag(IO::Handle &, const Tag &, File::Binary = File::Binary_yEnc, uint idt = 0);
static bool ParseTag(Tag &, const char *s, const char *e, const char **r = 0);
static bool LoadFromMemory(const char *, size_t, File &);
static File *Load(const char *, bool verbose = true);
static bool Load(const char *, File &, bool verbose = true);
static bool Save(IO::Handle &, const File &);
static bool Save(const char *, const File &);
static bool SaveBinary(IO::Handle &, const File &);
static bool SaveBinary(const char *, const File &);
};
#define NMLTagForeach(__I__, __T__) ListForeachPtr(GS::NML::Tag *, __I__, (__T__).GetTags())
#define NMLFileForeach(__I__, __F__) ListForeachPtr(GS::NML::Tag *, __I__, (__F__).GetTags())
} // NML
} // GS
#endif // __NMETALANG__

View File

@ -0,0 +1,60 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NMETAOBJECT__
#define __NMETAOBJECT__
#include "metafile/nml.h"
#include "reflection/c_refl.h"
/*!
@short Serialization helper.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
namespace GS {
namespace NML {
template <class T> bool LoadFromFile(T &object, File &file)
{
return file.isEmpty() ? false : object.FromMetaTag(*file.GetTags()[0]);
}
template <class T> bool LoadFromFile(T &object, const char *path, bool verbose = true)
{
File file;
file.name = path;
if (!Parser::Load(path, file, verbose))
return false;
return LoadFromFile(object, file);
}
template <class T> bool SaveToFile(T &object, File &file)
{
file.Clear();
return file.AddRoot(object.AsMetaTag()) ? true : false;
}
template <class T> bool SaveToFile(T &object, const char *path)
{
File file;
file.name = path;
if (!SaveToFile(object, file))
return false;
return Parser::Save(path, file);
}
bool GenericObjectFromMetaTag(Tag &, void *obj, Reflection::Property *obj_prop);
Tag *GenericObjectToMetaTag(Tag *, const void *obj, Reflection::Property *obj_prop);
bool GenericObjectFromMetaFile(const char *, void *obj, Reflection::Property *obj_prop, const char *root_name = 0);
bool GenericObjectToMetaFile(const char *, const void *obj, Reflection::Property *obj_prop, const char *root_name = 0);
} // NML
} // GS
#endif // __NMETAOBJECT__

View File

@ -0,0 +1,28 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NMETAFILE_TO_STRING__
#define __NMETAFILE_TO_STRING__
namespace GS {
class String;
namespace NML {
class Tag;
class File;
bool TagToString(const Tag &, String &);
bool TagFromString(const String &, Tag &);
bool FileToString(const File &, String &);
bool FileFromString(const String &, File &);
} // NML
} // GS
#endif // __NMETAFILE_TO_STRING__

View File

@ -0,0 +1,341 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NPICTURE__
#define __NPICTURE__
#include "geometry/rect.h"
#include "picture/pict_color_format.h"
#include "memory/bit_field.h"
#include "memory/nshared_ptr.h"
namespace GS {
struct Color;
struct Vector4;
class Gradient;
/*!
@short The base image class.
When used with PictureTools, this class provides high-quality sub-pixel
bitmap manipulations from shrinking/enlargement to blit/resize.
Importing/exporting from common image formats can be done through the
GS::PictureIO class.
@author Emmanuel Julien (ejulien@nworks.fr)
*/
class Picture : public SharedObject
{
public:
NPLACEMENT_NEW(Picture)
enum BlendMode
{
BlendReplace = 0,
BlendCompose,
BlendComposeFast,
BlendAdd,
BlendMultiply,
BlendMultiply2x,
BlendAlphaAdd,
BlendAlphaMultiply,
BlendAlphaMultiply2x,
RgbToAlpha
};
protected:
uchar *data; ///< Internal pointer to the picture's data.
uint hash, ///< Raster data hash value.
width, ///< Object's width.
height; ///< Object's height.
PixelFormat pxformat; ///< Pixel format.
/// Zeroify the class but do not free anything.
void Zeroify();
/*!
@short Internal free.
@note Free raster data only.
*/
void FreeData();
enum
{
PictureIsStub = (1 << 1)
};
BitField protected_flag;
public:
enum
{
HasForeignData = (1 << 1)
};
BitField pic_flag;
String name;
/*!
@name Blit functions.
@{
*/
/// Blit.
static bool Blit(const Picture &src, Picture &dst, const Rect <int> *src_rect = 0, const Rect <int> *dst_rect = 0, BlendMode op = BlendReplace);
/// Blit using a mask.
static bool BlitMask(const Picture &src, Picture &dst, Picture &mask, const Rect <int> *src_rect = 0, const Rect <int> *dst_rect = 0);
/*!
@short Scaled blit.
This function is designed to be used in high quality compositing
and perform a bilinear filtered sub-pixel blit.
@note When a rectangle is omitted the whole picture is used.
*/
static bool ScaleBlit(Picture &src, Picture &dst, Rect <float> *src_rect = 0, Rect <float> *dst_rect = 0);
/*!
@}
@name Cropping/framing functions.
@{
*/
/*!
@short Reframe picture.
All offsets may be negative.
Fill color can be specified and defaults to black.
@note Reframe(-2, -2, 2, 2) to display a 2 pixel-wide frame around
the picture.
*/
bool Reframe(int offset_sx, int offset_sy, int offset_ex, int offset_ey, const Color *fill = 0);
/// Crop picture to specified dimension.
bool Crop(uint target_width, uint target_height)
{ return (target_width <= width) && (target_height <= height) ? Reframe(0, 0, target_width - width, target_height - height) : false; }
/*!
@}
@name Rescaling functions.
@{
*/
/*!
@short Downscale a picture using area-summing filtering.
@note 0 can be used on width or height to resize the picture
proportionally.
*/
bool Downscale(uint width, uint height);
/*!
@short Resize a picture using bilinear filtering.
@note 0 can be used on width or height to resize the picture
proportionally.
*/
bool Resize(uint width, uint height);
/// Flip picture.
bool Flip(bool flip_h, bool flip_v);
/*!
@}
@name Color conversion functions.
@{
*/
protected:
bool RealToIntegerConversion(const PixelFormat &);
bool IntegerToIntegerConversion(const PixelFormat &);
bool Fast8888Conversion(const PixelFormat &);
public:
bool Swizzle(uchar r = 0, uchar g = 1, uchar b = 2, uchar a = 3);
/// Convert YUV buffers to RGB buffer.
static void YUV422toRGB32(uchar * const yuv_plane[3], uchar *rgb32, int width, int height, int dst_pitch = 0, int dst_height = 0);
/// Alpha blend two 32bit RGBA values together.
static uint ColorBlend(uint u, uint v, float opacity);
static void AlphaCompositePixel(uchar *data, uchar r, uchar g, uchar b, uchar a);
static uchar AlphaCompositeAlpha(uchar a, uchar b);
static uchar AlphaCompositeColor(uchar u, uchar v, uchar a, uchar b, uchar k);
bool ToGrayscale();
void Negative(bool r = true, bool g = true, bool b = true, bool a = false);
void UnpackYCbCr(uchar *y, uchar *cb, uchar *cr);
void PackYCbCr(uchar *y, uchar *cb, uchar *cr);
/*!
@}
@name Sampling functions.
@{
*/
void Sample(float u, float v, Color &out, uint _w = 0, uint _h = 0) const;
void Sample(float u, float v, uint &out, uint _w = 0, uint _h = 0) const;
void SampleRGBA(float u, float v, Color &out, uint _w = 0, uint _h = 0) const;
uint SampleInteger(float u, float v, uint _w = 0, uint _h = 0) const;
Color SampleColor(float u, float v, uint _w = 0, uint _h = 0) const;
Color SampleRGBAColor(float u, float v, uint _w = 0, uint _h = 0) const;
/*!
@}
@name Drawing functions.
@note Most of these functions are for now extremely slow!
@{
*/
protected:
/// Low-level draw line.
void LowLevelDrawLine(bool hq, float sx, float sy, float ex, float ey, float r, float g, float b, float a = 1, const Rect <float> *clip_rect = 0);
public:
/// Fill picture with a given color.
bool Fill(float r, float g, float b, float a = 1, const Rect <int> *clip_rect = 0, bool lock_alpha = false);
/// Draw a gradient.
void DrawGradient(const Gradient &gradient, const Rect <int> *clip_rect = 0);
/*!
@short Apply a convolution kernel to the picture.
@note Do not use in time critical code as this function is slow
and uses a temporary copy of the picture.
*/
bool ApplyConvolution(uint kernel_width, uint kernel_height, const int *weights, int weight = 256, int pass = 1, const Rect <int> *clip_rect = 0);
void DrawPlot(float x, float y, float r, float g, float b, float a = 1, const Rect <float> *clip_rect = 0);
void DrawPlotHQ(float x, float y, float r, float g, float b, float a = 1, const Rect <float> *clip_rect = 0);
void DrawLine(float sx, float sy, float ex, float ey, float r, float g, float b, float a = 1, const Rect <float> *clip_rect = 0);
void DrawLineHQ(float sx, float sy, float ex, float ey, float r, float g, float b, float a = 1, const Rect <float> *clip_rect = 0);
void DrawPolygon(uint point_count, Point <float> *point, float r, float g, float b, float a = 1, const Rect <float> *clip_rect = 0);
/// @}
bool ComputeHash();
int GetHash() const;
bool Compare(const Picture &picture) const;
/// Clone the picture via assignment operator.
void operator = (Picture &picture) { Clone(picture); }
/// Convert the picture to another pixel formats.
bool Convert(const PixelFormatDescription &);
/// Set the picture format without performing any data conversion.
bool SetFormat(const PixelFormatDescription &);
/*!
@short Set the picture dimensions but do not perform any allocation.
This function is used by the 3d engine built on the picture object.
It should not have any practical usage in standard usage.
*/
void Stub(uint w, uint h);
/// Is stub.
inline bool IsStub() const { return protected_flag.IsSet(PictureIsStub); }
/*!
@short Return image dimensions as a nfRect.
@note sx and sy are 0. Only ex and ey are relevant.
*/
inline iRect GetRect() const { return iRect(0, 0, width, height); }
/*!
@short Return image dimensions as a rectangle.
@note sx and sy are 0. Only ex and ey are relevant.
*/
inline void GetRect(iRect &rect) const { rect.Set(0, 0, width, height); }
/// Test is the picture has an alpha component.
bool HasAlpha() const;
inline uchar *GetData() const { return data; }
uchar *GetDataOffset(uint offset_x, uint offset_y) const { return data + (offset_x + offset_y * GetWidth()) * (pxformat.GetBpp() / 8); }
inline uint GetWidth() const { return width; }
inline uint GetHeight() const { return height; }
inline uchar GetBpp() const { return pxformat.GetBpp(); }
inline uint GetPitch() const { return (width * (pxformat.GetBpp() / 8)); }
inline bool isValid() const { return (width && height && data); }
/// Return the pixel format descriptor of the picture.
inline const PixelFormat &GetPixelFormat() const { return pxformat; }
void Clone(const Picture &, bool clone_data = true);
/*
@name Memory allocator.
@{
*/
virtual uchar *AllocMemory(size_t);
virtual void FreeMemory(uchar *);
/// @}
/*!
@short Set the picture object raster data source.
@note Ownership of the data buffer can be passed to this object.
*/
virtual void SetData(void *data, uint w, uint h, const PixelFormatDescription & = PixelFormat::RGBA8, bool take_ownership = false);
/*!
@short Allocate internal buffers overriding object settings.
@note Ownership of the data buffer is passed to this object.
@note If the internals already match the new settings this
function returns without doing anything unless user data is
passed.
@note If you provide the picture raster data buffer, you must make
sure that the pointer you pass to this function as user_data
is at least large enough to hold the complete picture in
memory.
@see SetData().
*/
virtual bool AllocAs(uint w, uint h, const PixelFormatDescription & = PixelFormat::RGBA8);
/*!
@short Free all object's data.
@note If you used the SetData() function the passed buffer will
not be freed by this object. You are responsible for
cleaning memory in such case.
*/
virtual void Free()
{
FreeData();
Zeroify();
}
Picture(const Picture &p)
{
Zeroify();
Clone(p);
}
Picture(void *data, uint w, uint h, const PixelFormatDescription &f = PixelFormat::RGBA8, bool take_ownership = false)
{
Zeroify();
SetData(data, w, h, f, take_ownership);
}
Picture(uint w, uint h, const PixelFormatDescription &f = PixelFormat::RGBA8)
{
Zeroify();
AllocAs(w, h, f);
}
Picture() { Zeroify(); }
virtual ~Picture();
};
typedef SharedPtr <Picture> sPicture;
} // GS
#endif // __NPICTURE__

View File

@ -0,0 +1,147 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NCOLORFORMAT__
#define __NCOLORFORMAT__
#include "nstring/nstring.h"
namespace GS {
/// The color space for a pixel format.
enum PixelColorSpace
{
PixelColorSpace_NULL = 0,
PixelColorSpace_RGB ///< Standard RGB space.
};
/// Pixel format descriptor.
struct PixelFormatDescription
{
PixelColorSpace space;
/*!
When working with integer values these are actual bit masks.
However when working with real values they are byte sized offsets
in the pixel packet to access a given component.
*/
uint amask, rmask, gmask, bmask;
uchar bpp;
bool real;
};
/*!
@short Structure holding a picture pixel format.
@note This structure only works with continuous bit masks.
@author Emmanuel Julien (ejulien@nworks.fr)
*/
struct PixelFormat
{
// Predefined pixel formats.
static PixelFormatDescription NONE;
static PixelFormatDescription BGRA8;
static PixelFormatDescription RGBA8;
static PixelFormatDescription ARGB8;
static PixelFormatDescription BGR8;
static PixelFormatDescription RGB8;
static PixelFormatDescription RGB555;
static PixelFormatDescription RGB565;
static PixelFormatDescription RGBA4444;
static PixelFormatDescription RGBF;
static PixelFormatDescription RGBAF;
static PixelFormatDescription YUYV;
PixelFormatDescription desc;
uchar ashift, rshift, bshift, gshift;
uchar acount, rcount, bcount, gcount;
/// Get format name (only use for cosmetic purposes! This is not a reliable naming convention).
String GetName() const;
/// Internal function to parse a bit mask.
void LoadMask(uint mask, uchar &shift, uchar &count)
{
shift = Memory::GetShiftCount(mask);
count = Memory::GetBitCount(mask);
}
/// Compare a format descriptor to this format.
bool operator == (const PixelFormatDescription &fmt) const
{
if ( (fmt.space != desc.space) || (fmt.bpp != desc.bpp) ||
(fmt.amask != desc.amask) || (fmt.rmask != desc.rmask) ||
(fmt.gmask != desc.gmask) || (fmt.bmask != desc.bmask) ||
(fmt.real != desc.real) )
return false;
return true;
}
/// Compare a format descriptor to this format.
bool operator != (const PixelFormatDescription &fmt) const
{ return !(*this == fmt); }
/// Return the format bpp.
uchar GetBpp() const { return desc.bpp; }
/// Is format using real or integer numbers.
bool IsReal() const { return desc.real; }
/// Set the the pixel format from user provided data.
void Set
(
PixelColorSpace space = PixelColorSpace_RGB,
uint amask = 0xff000000,
uint rmask = 0x00ff0000,
uint gmask = 0x0000ff00,
uint bmask = 0x000000ff,
uchar bpp = 32,
bool real = false
)
{
desc.amask = amask;
desc.rmask = rmask;
desc.gmask = gmask;
desc.bmask = bmask;
desc.bpp = bpp;
desc.space = space;
LoadMask(amask, ashift, acount);
LoadMask(rmask, rshift, rcount);
LoadMask(gmask, gshift, gcount);
LoadMask(bmask, bshift, bcount);
desc.real = real;
}
/// Set the the pixel format from a descriptor.
void Set(const PixelFormatDescription &fmt)
{ Set(fmt.space, fmt.amask, fmt.rmask, fmt.gmask, fmt.bmask, fmt.bpp, fmt.real); }
/// Return a reference to the format descriptor.
const PixelFormatDescription &GetDesc() const { return desc; }
/// Format a color for this color format.
uint Format(float r, float g, float b, float a = 1) const;
/// Constructor.
PixelFormat
(
PixelColorSpace space = PixelColorSpace_RGB,
uint amask = 0xff000000,
uint rmask = 0x00ff0000,
uint gmask = 0x0000ff00,
uint bmask = 0x000000ff,
uchar bpp = 32,
bool real = false
)
{ Set(space, amask, rmask, gmask, bmask, bpp, real); }
/// Constructor via a format descriptor.
PixelFormat(const PixelFormatDescription &desc)
{ Set(desc); }
};
} // GS
#endif // __NCOLORFORMAT__

View File

@ -0,0 +1,51 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NCOLORGRADIENT__
#define __NCOLORGRADIENT__
#include "ntypes.h"
#include "picture/pict.h"
#include "color/color.h"
namespace GS {
/*
@short Color gradient.
@author Emmanuel Julien (ejulien@nworks.fr)
*/
class Gradient
{
uint control_point_count;
Picture::BlendMode op;
public:
float k[8]; ///< Gradient coefficient.
Color color[8]; ///< Gradient color.
inline uint GetControlPointCount() const { return control_point_count; }
inline Picture::BlendMode GetOperator() const { return op; }
inline void SetOperator(Picture::BlendMode _op) { op = _op; }
inline void Reset() { control_point_count = 0; }
bool FromMetaTag(NML::Tag *);
Gradient()
{
control_point_count = 0;
op = Picture::BlendMultiply;
}
};
} // GS
#endif // __NCOLORGRADIENT__

View File

@ -0,0 +1,67 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
------------------------------------------------------------------------------*/
#ifndef __NPICTUREIO__
#define __NPICTUREIO__
#include "picture/pict_io_codec.h"
#include "memory/singleton.h"
#include "container/nlist.h"
namespace GS {
/*
@short Picture I/O class.
@author Emmanuel Julien (ejulien@nworks.fr)
*/
class PictureIO : public Singleton <PictureIO>
{
AutoList <PictureCodec *> codec_list;
public:
/*!
@short Generic load function.
This function try to load a given resource using all registered
codec. This is a convenience function and is not designed to be
fast. If you know the file format you are working with then please
directly use the appropriate codec.
*/
bool Load(Picture &, const char *uri);
/// Save a picture through a given codec.
bool Save(const Picture &, const char *uri, const char *codec_name);
/// Return a codec from its ID or the file extension it supports.
PictureCodec *Codec(const char *codec_name);
/// Register an I/O codec inside the manager.
bool RegisterCodec(PictureCodec *, bool verbose = false);
/// Delete all registered codec.
void DeleteCodecs() { codec_list.Clear(); }
/// Load a BMP resource via the core codec.
bool BmpLoad(Picture &, IO::Handle &);
/*!
@short Load a TARGA (TGA) resource via the core codec.
@note Supported color format are BGRA8/BGR8/RGB24/RGB555
both RLE and RAW.
*/
bool TgaLoad(Picture &, IO::Handle &);
/*!
@short Save a picture to TARGA (TGA) via the core codec.
@note Supported color format are BGRA8/BGR8/RGB24/RGB555.
*/
bool TgaSave(const Picture &, const char *uri);
};
} // GS
#endif // __NPICTUREIO__

View File

@ -0,0 +1,51 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
------------------------------------------------------------------------------*/
#ifndef __NPICTUREIOCODEC__
#define __NPICTUREIOCODEC__
#include "filesystem/io_handle.h"
#include "nstring/nstring.h"
namespace GS {
class Picture;
/*
@short Picture I/O codec.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
struct PictureCodec
{
enum
{
NoCaps = 0,
CanRead = (1 << 0), ///< Codec can read data.
CanWrite = (1 << 1), ///< Codec can write data.
WriteRaw = (1 << 2), ///< Codec supports raw output.
WriteLossy = (1 << 3), ///< Codec supports lossy compression.
WriteLossless = (1 << 4), ///< Codec supports lossless compression.
AlphaChannel = (1 << 5), ///< Codec supports alpha channel.
RealData = (1 << 6) ///< Codec works on real data.
};
virtual bool Load(IO::Handle &, Picture &) = 0;
virtual bool Save(IO::Handle &, const Picture &) { return false; }
virtual const char *GetName() const = 0;
virtual const char *GetDesc() const = 0;
virtual uint GetCaps() const = 0;
virtual ~PictureCodec() {}
};
} // GS
#endif // __NPICTUREIOCODEC__

View File

@ -0,0 +1,22 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
------------------------------------------------------------------------------*/
#ifndef __PICT_TOOLS__
#define __PICT_TOOLS__
namespace GS {
class Picture;
namespace PictureTools {
/// Compare two pictures.
bool Compare(const Picture &, const Picture &, float threshold = 0.f);
} // PictureTools
} // GS
#endif // __PICT_TOOLS__

View File

@ -0,0 +1,114 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __PLUGIN_MANAGER__
#define __PLUGIN_MANAGER__
#include "shared/shared_library.h"
#include "plugin/shared_systems.h"
#include "container/nlist.h"
#include "nstring/nstring.h"
#include "platform.h"
namespace GS {
static const int PluginLoadOk = 0;
static const int PluginLoadError = 1;
static const int PluginMissingClass = 2;
static const int PluginClassError = 3;
static const int PluginMissingVersion = 4;
static const int PluginVersionError = 5;
static const int PluginInterfaceError = 6;
/*!
@short Plugin manager
@author Emmanuel Julien (ejulien@owloh.com)
*/
template <class T> class PluginManager
{
typedef void SetSharedSystems(SharedSystems &);
typedef T *Factory();
typedef const char *GetPluginClass();
typedef uint GetPluginVersion();
public:
struct Plugin
{
String path;
AutoPtr <ISharedLib> shared_lib;
};
private:
AutoList <Plugin *> plugins;
public:
/// Return a new instance to concrete interface the plugin implements.
T *CreatePluginInterface(Plugin *p)
{
Factory *p_factory = p ? (Factory *)p->shared_lib->GetFunctionPointer("createPluginInterface") : 0;
return p_factory ? p_factory() : 0;
}
/*
@short Load a plugin.
The plugin is dynamically loaded from the specified path and its
class and version are checked for compatibility with the host
interface class and version.
A return code can be passed to get more information on failure.
*/
Plugin *LoadPlugin(const char *path, int *code = 0)
{
AutoPtr <Plugin> p(new Plugin);
if (p.IsNull())
return 0;
if (code)
*code = PluginLoadOk;
#define Error(V) { if (code) *code = V; return 0; }
p->shared_lib = Platform::Get().LoadSharedLibrary(path);
if (p->shared_lib.IsNull())
Error(PluginLoadError);
GetPluginClass *get_plugin_class = (GetPluginClass *)p->shared_lib->GetFunctionPointer("getPluginClass");
GetPluginVersion *get_plugin_version = (GetPluginVersion *)p->shared_lib->GetFunctionPointer("getPluginVersion");
SetSharedSystems *set_shared_systems = (SetSharedSystems *)p->shared_lib->GetFunctionPointer("setSharedSystems");
if (!get_plugin_class)
Error(PluginMissingClass);
if (!get_plugin_version)
Error(PluginMissingVersion);
if (!set_shared_systems)
Error(PluginInterfaceError);
if (String(T::GetPluginClass()) != get_plugin_class())
Error(PluginClassError);
if (T::GetPluginVersion() != get_plugin_version())
Error(PluginVersionError);
// Set the shared platform pointer.
SharedSystems shared;
set_shared_systems(shared);
p->path = path;
plugins.Add(p);
return p.Detach();
}
};
} // GS
#endif // __PLUGIN_MANAGER__

View File

@ -0,0 +1,37 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __SHARED_SYSTEMS__
#define __SHARED_SYSTEMS__
namespace GS {
class Platform;
class AudioIO;
class PictureIO;
class LogSystem;
class SharedSystems
{
Platform *platform;
LogSystem *log_system;
PictureIO *picture_io;
AudioIO *audio_io;
public:
/// Call from the master module responsible for instantiating plugins.
void Get();
/// Call from a dynamically module to share the master module systems.
void Set();
SharedSystems() : platform(0), log_system(0), picture_io(0), audio_io(0) { Get(); }
};
} // GS
#endif // __SHARED_SYSTEMS__

View File

@ -0,0 +1,31 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NSHAPE__
#define __NSHAPE__
#include "math/vector.h"
namespace GS {
/*!
@short Shape base class.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
struct Shape
{
/// Get shape center.
virtual Vector4 &GetCenter() const = 0;
/// Get distance to support point on a given direction.
virtual float GetSupportDistance(const Vector4 &) const = 0;
};
} // GS
#endif // __NSHAPE__

View File

@ -0,0 +1,47 @@
/*
nEngine
Emmanuel Julien 2000-2010
All Rights Reserved
http://www.gamestart3d.com
Please refer to the included license.txt for license informations.
*/
#ifndef __NSHAPEBOX__
#define __NSHAPEBOX__
#include "shape/shape.h"
/*!
@short Box shape class.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
struct nBoxShape : public nShape
{
Vector4 center;
Vector4 half_d;
virtual Vector4 &GetCenter() const
{ return center; }
virtual float GetSupportDistance(const Vector4 &d) const
{ return d.Abs().Dot(half_d); }
nSphereShape(const Vector4 &c, const Vector4 &d)
{
center = c;
half_d = d;
}
nSphereShape()
{
center.Set(0, 0, 0);
half_d.Set(0, 0, 0);
}
};
#endif // __NSHAPEBOX__

View File

@ -0,0 +1,59 @@
/*
nEngine
Emmanuel Julien 2000-2010
All Rights Reserved
http://www.gamestart3d.com
Please refer to the included license.txt for license informations.
*/
#ifndef __NSHAPECONVEX__
#define __NSHAPECONVEX__
#include "shape/shape.h"
#include "container/narray.h"
/*!
@short Convex shape class.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
struct nConvexShape : public nShape
{
Vector4 center;
nArray <Vector4> vtx;
virtual Vector4 &GetCenter() const
{ return center; }
virtual float GetSupportDistance(const Vector4 &d) const
{
if (!vtx.GetCount())
return 0;
float d = vtx[0].Dot(d);
for (uint n = 1; n < vtx.GetCount(); ++n)
{
float _d = vtx[n].Dot(d);
if (_d > d)
d = _d;
}
return d;
}
nConvexShape(const Vector4 &c, const nArray <Vector4> &v)
{
center = c;
vtx.Clone(v);
}
nConvexShape()
{
center.Set(0, 0, 0);
}
};
#endif // __NSHAPECONVEX__

View File

@ -0,0 +1,47 @@
/*
nEngine
Emmanuel Julien 2000-2010
All Rights Reserved
http://www.gamestart3d.com
Please refer to the included license.txt for license informations.
*/
#ifndef __NSHAPESPHERE__
#define __NSHAPESPHERE__
#include "shape/shape.h"
/*!
@short Sphere shape class.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
struct nSphereShape : public nShape
{
Vector4 center;
float radius;
virtual Vector4 &GetCenter() const
{ return center; }
virtual float GetSupportDistance(const Vector4 &) const
{ return radius; }
nSphereShape(const Vector4 &c, float r)
{
center = c;
radius = r;
}
nSphereShape()
{
center.Set(0, 0, 0);
radius = 0;
}
};
#endif // __NSHAPESPHERE__

View File

@ -0,0 +1,111 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NSORT__
#define __NSORT__
#include "ntypes.h"
#include "container/narray.h"
namespace GS {
/*!
Sort class.
Can sort floating point numbers using QuickSort.
Can also sort integer numbers using Radix sort (byte-sort).
Use T to specify the type of value to sort and O to track a user value in
the sorted array (for example an index into the unsorted array).
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
template <typename T, typename O> struct Sort
{
//----------------------------------------------------------------------
struct Entry
{
T v;
O o;
};
//----------------------------------------------------------------------
protected:
static void inline SwapEntries(Entry &a, Entry &b)
{ Entry t = a; a = b; b = t; }
static void RecurseQuickSort(Entry *entries, int left, int right)
{
if (left >= right)
return;
int pivot = (left + right) >> 1;
SwapEntries(entries[left], entries[pivot]);
int ls = left;
for (int cr = left + 1; cr <= right; ++cr)
if (entries[cr].v < entries[left].v)
SwapEntries(entries[cr], entries[++ls]);
SwapEntries(entries[left], entries[ls]);
RecurseQuickSort(entries, left, ls - 1);
RecurseQuickSort(entries, ls + 1, right);
}
public:
/// Quicksort n entries in-place.
static void QuickSort(int n, Entry *entries)
{
RecurseQuickSort(entries, 0, n - 1);
}
/// Byte-sort sort n entries from in to out.
static Array <Entry> *ByteSort(uint n, Array <Entry> *a, Array <Entry> *b)
{
if (!a || !b)
return 0;
uint radix[257];
for (size_t pass = 0; pass < sizeof(T); ++pass)
{
// clear radix buffer
for (uint i = 0; i < 257; ++i)
radix[i] = 0;
// count radix
for (uint i = 0; i < n; ++i)
++radix[uint((*a)[i].v & 255) + 1];
// convert count to index
for (uint i = 0; i < 256; ++i)
radix[i + 1] += radix[i];
// insert values
for (uint i = 0; i < n; i++)
{
const uint p = radix[uint((*a)[i].v & 255)]++;
(*b)[p].v = (*a)[i].v >> 8; // transfer & shift radix
(*b)[p].o = (*a)[i].o;
}
// swap arrays
Array <Entry> *tmp = b; b = a; a = tmp;
}
return a;
}
//----------------------------------------------------------------------
};
} // GS
#endif

View File

@ -0,0 +1,51 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NBENCHMARK__
#define __NBENCHMARK__
#include "time/ntime.h"
#include "container/smart_median_average.h"
namespace GS {
/*!
@short Benchmark.
@author Emmanuel Julien (ejulien@owloh.com)
*/
class Benchmark
{
SmartMedianAverage <float> avg;
Time r_clock, t_clock;
public:
void Start();
void Stop();
float GetMs() const;
void Reset();
Benchmark(bool start = false);
};
/// Scoped benchmark.
struct ScopedBenchmark
{
Benchmark &bench;
ScopedBenchmark(Benchmark &b) : bench(b)
{ bench.Start(); }
~ScopedBenchmark()
{ bench.Stop(); }
};
} // GS
#endif // __NBENCHMARK__

View File

@ -0,0 +1,42 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NLOOPBENCHMARK__
#define __NLOOPBENCHMARK__
#include "time/ntime.h"
namespace GS {
/*!
@short Loop benchmark tool.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
class LoopBenchmark
{
uint loop_count;
Time r_time, t_time;
float ms;
public:
void MarkLoop();
float GetMs() const;
float GetFps() const;
void Reset();
LoopBenchmark() : loop_count(0), ms(0) {}
};
} // GS
#endif // __NLOOPBENCHMARK__

View File

@ -0,0 +1,77 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __NPROFILER__
#define __NPROFILER__
#include "timing/benchmark.h"
namespace GS {
/*!
@short Profiler.
@author Emmanuel Julien (ejulien@owloh.com)
*/
struct Profiler
{
// System is owned by the profiler.
struct System
{
String label;
Benchmark profile;
AutoList <System *> sub_systems;
void Reset()
{
profile.Reset();
ListForeachPtr(System *, s, sub_systems)
s->Reset();
}
};
AutoList <System *> root_systems;
/*!
@short Declare a system.
The system can be declared as a sub-system of another system.
*/
System *DeclareSystem(const char *label, System *subsystem_of = 0)
{
System *sys = new System;
if (sys == 0)
return 0;
sys->label = label;
if (subsystem_of)
subsystem_of->sub_systems.Add(sys);
else
root_systems.Add(sys);
return sys;
}
/// Reset all system in the profiler.
virtual void ResetProfiles()
{
ListForeachPtr(System *, s, root_systems)
s->Reset();
}
};
#if __ENGINE_RETAIL__
#define ScopedSystemProfile(_System) ;
#else
#define ScopedSystemProfile(_System) ScopedBenchmark _scoped_profile(_System->profile);
#endif
} // GS
#endif // __NPROFILER__