First commit
This commit is contained in:
parent
2885926e15
commit
c398fa4da4
|
@ -0,0 +1,65 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "Box.h"
|
||||||
|
#include "Collision.h"
|
||||||
|
|
||||||
|
using namespace ::Oyster::Collision;
|
||||||
|
using namespace ::Oyster::Math;
|
||||||
|
|
||||||
|
Box::Box( ) : ICollideable(ICollideable::Box), orientation(Float4x4::identity), boundingOffset() {}
|
||||||
|
|
||||||
|
Box::Box( const Box &box ) : ICollideable(ICollideable::Box), orientation(box.orientation), boundingOffset(box.boundingOffset)
|
||||||
|
{
|
||||||
|
this->orientation = box.orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
Box::Box( const Float4x4 &o, const Float3 &s ) : ICollideable(ICollideable::Box), orientation(o), boundingOffset(s*0.5)
|
||||||
|
{
|
||||||
|
this->orientation = o;
|
||||||
|
}
|
||||||
|
Box::~Box( ) { /*Nothing needs to be done here*/ }
|
||||||
|
|
||||||
|
Box & Box::operator = ( const Box &box )
|
||||||
|
{
|
||||||
|
this->orientation = box.orientation;
|
||||||
|
this->boundingOffset = box.boundingOffset;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ICollideable* Box::clone( ) const
|
||||||
|
{ return new Box( *this ); }
|
||||||
|
|
||||||
|
bool Box::Intersects( const ICollideable *target ) const
|
||||||
|
{
|
||||||
|
switch( target->type )
|
||||||
|
{
|
||||||
|
case ICollideable::Point: return Utility::intersect( *this, *(Collision::Point*)target );
|
||||||
|
case ICollideable::Ray: return Utility::intersect( *this, *(Collision::Ray*)target, ((Collision::Ray*)target)->collisionDistance );
|
||||||
|
case ICollideable::Sphere: return Utility::intersect( *this, *(Collision::Sphere*)target );
|
||||||
|
case ICollideable::Plane: return Utility::intersect( *this, *(Collision::Plane*)target );
|
||||||
|
case ICollideable::Triangle: return false; // TODO
|
||||||
|
case ICollideable::BoxAxisAligned: return Utility::intersect( *this, *(Collision::BoxAxisAligned*)target );
|
||||||
|
case ICollideable::Box: return Utility::intersect( *this, *(Collision::Box*)target );
|
||||||
|
case ICollideable::Frustrum: return false; // TODO
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Box::Contains( const ICollideable *target ) const
|
||||||
|
{
|
||||||
|
switch( target->type )
|
||||||
|
{
|
||||||
|
case ICollideable::Point: return Utility::intersect( *this, *(Collision::Point*)target );
|
||||||
|
case ICollideable::Sphere: return false; // TODO
|
||||||
|
case ICollideable::Triangle: return false; // TODO
|
||||||
|
case ICollideable::BoxAxisAligned: return false; // TODO
|
||||||
|
case ICollideable::Box: return false; // TODO
|
||||||
|
case ICollideable::Frustrum: return false; // TODO
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ICollideable::State Box::Advanced( const ICollideable *target ) const
|
||||||
|
{ return ICollideable::Missed; } //Not supported returns 0
|
|
@ -0,0 +1,44 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef OYSTER_COLLISION_BOX_H
|
||||||
|
#define OYSTER_COLLISION_BOX_H
|
||||||
|
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "ICollideable.h"
|
||||||
|
|
||||||
|
namespace Oyster { namespace Collision
|
||||||
|
{
|
||||||
|
class Box : public ICollideable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct{ ::Oyster::Math::Float4x4 orientation; ::Oyster::Math::Float3 boundingOffset; };
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
::Oyster::Math::Float3 xAxis; ::Oyster::Math::Float paddingA;
|
||||||
|
::Oyster::Math::Float3 yAxis; ::Oyster::Math::Float paddingB;
|
||||||
|
::Oyster::Math::Float3 zAxis; ::Oyster::Math::Float paddingC;
|
||||||
|
::Oyster::Math::Float3 center;
|
||||||
|
};
|
||||||
|
char byte[sizeof(::Oyster::Math::Float4x4) + sizeof(::Oyster::Math::Float3)];
|
||||||
|
};
|
||||||
|
|
||||||
|
Box( );
|
||||||
|
Box( const Box &box );
|
||||||
|
Box( const ::Oyster::Math::Float4x4 &orientation, const ::Oyster::Math::Float3 &size );
|
||||||
|
~Box( );
|
||||||
|
|
||||||
|
Box & operator = ( const Box &box );
|
||||||
|
|
||||||
|
ICollideable* clone( ) const;
|
||||||
|
bool Intersects( const ICollideable *target ) const;
|
||||||
|
bool Contains( const ICollideable *target ) const;
|
||||||
|
ICollideable::State Advanced( const ICollideable *target ) const; //Not supported returns 0;
|
||||||
|
};
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,59 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "BoxAxisAligned.h"
|
||||||
|
#include "Collision.h"
|
||||||
|
|
||||||
|
using namespace ::Oyster::Collision;
|
||||||
|
using namespace ::Oyster::Math;
|
||||||
|
|
||||||
|
BoxAxisAligned::BoxAxisAligned( ) : ICollideable(ICollideable::BoxAxisAligned), minVertex(-0.5f,-0.5f,-0.5f), maxVertex(0.5f,0.5f,0.5f) {}
|
||||||
|
BoxAxisAligned::BoxAxisAligned( const BoxAxisAligned &box ) : ICollideable(ICollideable::BoxAxisAligned), minVertex(box.minVertex), maxVertex(box.maxVertex) {}
|
||||||
|
BoxAxisAligned::BoxAxisAligned( const Float3 &_minVertex, const Float3 &_maxVertex ) : ICollideable(ICollideable::BoxAxisAligned), minVertex(_minVertex), maxVertex(_maxVertex) {}
|
||||||
|
BoxAxisAligned::BoxAxisAligned( const Float &leftClip, const Float &rightClip, const Float &topClip, const Float &bottomClip, const Float &nearClip, const Float &farClip )
|
||||||
|
: ICollideable(ICollideable::BoxAxisAligned), minVertex(leftClip, bottomClip, nearClip), maxVertex(rightClip, topClip, farClip) {}
|
||||||
|
BoxAxisAligned::~BoxAxisAligned( ) { /*Nothing needs to be done here*/ }
|
||||||
|
|
||||||
|
BoxAxisAligned & BoxAxisAligned::operator = ( const BoxAxisAligned &box )
|
||||||
|
{
|
||||||
|
this->minVertex = box.minVertex;
|
||||||
|
this->maxVertex = box.maxVertex;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ICollideable* BoxAxisAligned::clone( ) const
|
||||||
|
{ return new BoxAxisAligned( *this ); }
|
||||||
|
|
||||||
|
bool BoxAxisAligned::Intersects( const ICollideable *target ) const
|
||||||
|
{
|
||||||
|
switch( target->type )
|
||||||
|
{
|
||||||
|
case ICollideable::Point: return Utility::intersect( *this, *(Collision::Point*)target );
|
||||||
|
case ICollideable::Ray: return Utility::intersect( *this, *(Collision::Ray*)target, ((Collision::Ray*)target)->collisionDistance );
|
||||||
|
case ICollideable::Sphere: return Utility::intersect( *this, *(Collision::Sphere*)target );
|
||||||
|
case ICollideable::Plane: return Utility::intersect( *this, *(Collision::Plane*)target );
|
||||||
|
case ICollideable::Triangle: return false; // TODO
|
||||||
|
case ICollideable::BoxAxisAligned: return Utility::intersect( *this, *(Collision::BoxAxisAligned*)target );
|
||||||
|
case ICollideable::Box: return false; // TODO
|
||||||
|
case ICollideable::Frustrum: return false; // TODO
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BoxAxisAligned::Contains( const ICollideable *target ) const
|
||||||
|
{
|
||||||
|
switch( target->type )
|
||||||
|
{
|
||||||
|
case ICollideable::Point: return false; // TODO
|
||||||
|
case ICollideable::Sphere: return false; // TODO
|
||||||
|
case ICollideable::Triangle: return false; // TODO
|
||||||
|
case ICollideable::BoxAxisAligned: return false; // TODO
|
||||||
|
case ICollideable::Box: return false; // TODO
|
||||||
|
case ICollideable::Frustrum: return false; // TODO
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ICollideable::State BoxAxisAligned::Advanced( const ICollideable *target ) const
|
||||||
|
{ return ICollideable::Missed; } //Not supported returns 0
|
|
@ -0,0 +1,38 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef OYSTER_COLLISION_BOXAXISALIGNED_H
|
||||||
|
#define OYSTER_COLLISION_BOXAXISALIGNED_H
|
||||||
|
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "ICollideable.h"
|
||||||
|
|
||||||
|
namespace Oyster { namespace Collision
|
||||||
|
{
|
||||||
|
class BoxAxisAligned : public ICollideable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct{ ::Oyster::Math::Float3 minVertex, maxVertex; };
|
||||||
|
char byte[2*sizeof(::Oyster::Math::Float3)];
|
||||||
|
};
|
||||||
|
|
||||||
|
BoxAxisAligned( );
|
||||||
|
BoxAxisAligned( const BoxAxisAligned &box );
|
||||||
|
BoxAxisAligned( const ::Oyster::Math::Float3 &minVertex, const ::Oyster::Math::Float3 &maxVertex );
|
||||||
|
BoxAxisAligned( const ::Oyster::Math::Float &leftClip, const ::Oyster::Math::Float &rightClip, const ::Oyster::Math::Float &topClip, const ::Oyster::Math::Float &bottomClip, const ::Oyster::Math::Float &nearClip, const ::Oyster::Math::Float &farClip );
|
||||||
|
~BoxAxisAligned( );
|
||||||
|
|
||||||
|
BoxAxisAligned & operator = ( const BoxAxisAligned &box );
|
||||||
|
|
||||||
|
ICollideable* clone( ) const;
|
||||||
|
bool Intersects( const ICollideable *target ) const;
|
||||||
|
bool Contains( const ICollideable *target ) const;
|
||||||
|
ICollideable::State Advanced( const ICollideable *target ) const; //Not supported returns 0;
|
||||||
|
};
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,665 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "Collision.h"
|
||||||
|
#include "Utilities.h"
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
using namespace Oyster::Math;
|
||||||
|
|
||||||
|
namespace Oyster { namespace Collision { namespace Utility
|
||||||
|
{
|
||||||
|
|
||||||
|
// PRIVATE HEADER ///////////////////////////////////////////////////
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
const Float epsilon = (const Float)1e-20;
|
||||||
|
|
||||||
|
// Float calculations can suffer roundingerrors. Which is where epsilon = 1e-20 comes into the picture
|
||||||
|
inline bool equalsZero( const Float &value )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
return ::Utility::Value::abs( value ) < epsilon;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float calculations can suffer roundingerrors. Which is where epsilon = 1e-20 comes into the picture
|
||||||
|
inline bool notEqualsZero( const Float &value )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
return ::Utility::Value::abs( value ) > epsilon;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns true if miss/reject
|
||||||
|
bool boxVsRayPerSlabCheck( const Float3 &axis, const Float &boundingOffset, const Float3 &deltaPos, const Float3 rayDirection, Float &tMin, Float &tMax )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float e = axis.dot( deltaPos ),
|
||||||
|
f = axis.dot( rayDirection );
|
||||||
|
if( equalsZero(f) ) // if axis is not parallell with ray
|
||||||
|
{
|
||||||
|
Float t1 = e + boundingOffset,
|
||||||
|
t2 = e - boundingOffset;
|
||||||
|
t1 /= f; t2 /= f;
|
||||||
|
if( t1 > t2 ) ::Utility::Element::swap( t1, t2 );
|
||||||
|
tMin = ::Utility::Value::max( tMin, t1 );
|
||||||
|
tMax = ::Utility::Value::min( tMax, t2 );
|
||||||
|
if( tMin > tMax ) return true;
|
||||||
|
if( tMax < 0.0f ) return true;
|
||||||
|
}
|
||||||
|
else if( boundingOffset < -e ) return true;
|
||||||
|
else if( boundingOffset < e ) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool contains( const Plane &container, const Float3 &pos )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
return equalsZero( container.normal.dot( pos ) + container.phasing );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void compare( Float &connectOffset, const Plane &plane, const Float3 &pos )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
connectOffset = plane.normal.dot(pos);
|
||||||
|
connectOffset += plane.phasing;
|
||||||
|
}
|
||||||
|
|
||||||
|
void compare( Float &boxExtend, Float ¢erDistance, const Plane &plane, const BoxAxisAligned &box )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float3 c = (box.maxVertex + box.minVertex) * 0.5f, // box.Center
|
||||||
|
h = (box.maxVertex - box.minVertex) * 0.5f; // box.halfSize
|
||||||
|
boxExtend = h.x * ::Utility::Value::abs(plane.normal.x); // Box max extending towards plane
|
||||||
|
boxExtend += h.y * ::Utility::Value::abs(plane.normal.y);
|
||||||
|
boxExtend += h.z * ::Utility::Value::abs(plane.normal.z);
|
||||||
|
centerDistance = c.dot(plane.normal) + plane.phasing; // distance between box center and plane
|
||||||
|
}
|
||||||
|
|
||||||
|
void compare( Float &boxExtend, Float ¢erDistance, const Plane &plane, const Box &box )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
boxExtend = box.boundingOffset.x * ::Utility::Value::abs(plane.normal.dot(box.orientation.v[0].xyz)); // Box max extending towards plane
|
||||||
|
boxExtend += box.boundingOffset.y * ::Utility::Value::abs(plane.normal.dot(box.orientation.v[1].xyz));
|
||||||
|
boxExtend += box.boundingOffset.z * ::Utility::Value::abs(plane.normal.dot(box.orientation.v[2].xyz));
|
||||||
|
|
||||||
|
centerDistance = box.orientation.v[3].xyz.dot(plane.normal) + plane.phasing; // distance between box center and plane
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fifteenAxisVsAlignedAxisOverlappingChecks( const Float3 &boundingOffsetA, const Float3 &boundingOffsetB, const Float4x4 &orientationB )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float4x4 absOrientationB;
|
||||||
|
{
|
||||||
|
Float4x4 tO = orientationB.getTranspose();
|
||||||
|
absOrientationB.v[0] = ::Utility::Value::abs(tO.v[0]);
|
||||||
|
if( absOrientationB.v[0].w > boundingOffsetA.x + boundingOffsetB.dot(absOrientationB.v[0].xyz) ) return false;
|
||||||
|
absOrientationB.v[1] = ::Utility::Value::abs(tO.v[1]);
|
||||||
|
if( absOrientationB.v[1].w > boundingOffsetA.y + boundingOffsetB.dot(absOrientationB.v[1].xyz) ) return false;
|
||||||
|
absOrientationB.v[2] = ::Utility::Value::abs(tO.v[2]);
|
||||||
|
if( absOrientationB.v[2].w > boundingOffsetA.z + boundingOffsetB.dot(absOrientationB.v[2].xyz) ) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
absOrientationB.transpose();
|
||||||
|
if( ::Utility::Value::abs(orientationB.v[3].dot(orientationB.v[0])) > boundingOffsetB.x + boundingOffsetA.dot(absOrientationB.v[0].xyz) ) return false;
|
||||||
|
if( ::Utility::Value::abs(orientationB.v[3].dot(orientationB.v[1])) > boundingOffsetB.x + boundingOffsetA.dot(absOrientationB.v[1].xyz) ) return false;
|
||||||
|
if( ::Utility::Value::abs(orientationB.v[3].dot(orientationB.v[2])) > boundingOffsetB.x + boundingOffsetA.dot(absOrientationB.v[2].xyz) ) return false;
|
||||||
|
|
||||||
|
// ( 1,0,0 ) x orientationB.v[0].xyz:
|
||||||
|
Float d = boundingOffsetA.y * absOrientationB.v[0].z;
|
||||||
|
d += boundingOffsetA.z * absOrientationB.v[0].y;
|
||||||
|
d += boundingOffsetB.y * absOrientationB.v[2].x;
|
||||||
|
d += boundingOffsetB.z * absOrientationB.v[1].x;
|
||||||
|
if( ::Utility::Value::abs(orientationB.v[3].z*orientationB.v[0].y - orientationB.v[3].y*orientationB.v[0].z) > d ) return false;
|
||||||
|
|
||||||
|
// ( 1,0,0 ) x orientationB.v[1].xyz:
|
||||||
|
d = boundingOffsetA.y * absOrientationB.v[1].z;
|
||||||
|
d += boundingOffsetA.z * absOrientationB.v[1].y;
|
||||||
|
d += boundingOffsetB.x * absOrientationB.v[2].x;
|
||||||
|
d += boundingOffsetB.z * absOrientationB.v[0].x;
|
||||||
|
if( ::Utility::Value::abs(orientationB.v[3].z*orientationB.v[1].y - orientationB.v[3].y*orientationB.v[1].z) > d ) return false;
|
||||||
|
|
||||||
|
// ( 1,0,0 ) x orientationB.v[2].xyz:
|
||||||
|
d = boundingOffsetA.y * absOrientationB.v[2].z;
|
||||||
|
d += boundingOffsetA.z * absOrientationB.v[2].y;
|
||||||
|
d += boundingOffsetB.x * absOrientationB.v[1].x;
|
||||||
|
d += boundingOffsetB.y * absOrientationB.v[0].x;
|
||||||
|
if( ::Utility::Value::abs(orientationB.v[3].z*orientationB.v[2].y - orientationB.v[3].y*orientationB.v[2].z) > d ) return false;
|
||||||
|
|
||||||
|
// ( 0,1,0 ) x orientationB.v[0].xyz:
|
||||||
|
d = boundingOffsetA.x * absOrientationB.v[0].z;
|
||||||
|
d += boundingOffsetA.z * absOrientationB.v[0].x;
|
||||||
|
d += boundingOffsetB.y * absOrientationB.v[2].y;
|
||||||
|
d += boundingOffsetB.z * absOrientationB.v[1].y;
|
||||||
|
if( ::Utility::Value::abs(orientationB.v[3].x*orientationB.v[0].z - orientationB.v[3].z*orientationB.v[0].x) > d ) return false;
|
||||||
|
|
||||||
|
// ( 0,1,0 ) x orientationB.v[1].xyz:
|
||||||
|
d = boundingOffsetA.x * absOrientationB.v[1].z;
|
||||||
|
d += boundingOffsetA.z * absOrientationB.v[1].x;
|
||||||
|
d += boundingOffsetB.x * absOrientationB.v[2].y;
|
||||||
|
d += boundingOffsetB.z * absOrientationB.v[0].y;
|
||||||
|
if( ::Utility::Value::abs(orientationB.v[3].x*orientationB.v[1].z - orientationB.v[3].z*orientationB.v[1].x) > d ) return false;
|
||||||
|
|
||||||
|
// ( 0,1,0 ) x orientationB.v[2].xyz:
|
||||||
|
d = boundingOffsetA.x * absOrientationB.v[2].z;
|
||||||
|
d += boundingOffsetA.z * absOrientationB.v[2].x;
|
||||||
|
d += boundingOffsetB.x * absOrientationB.v[1].y;
|
||||||
|
d += boundingOffsetB.y * absOrientationB.v[0].y;
|
||||||
|
if( ::Utility::Value::abs(orientationB.v[3].x*orientationB.v[2].z - orientationB.v[3].z*orientationB.v[2].x) > d ) return false;
|
||||||
|
|
||||||
|
// ( 0,0,1 ) x orientationB.v[0].xyz:
|
||||||
|
d = boundingOffsetA.x * absOrientationB.v[0].y;
|
||||||
|
d += boundingOffsetA.y * absOrientationB.v[0].x;
|
||||||
|
d += boundingOffsetB.y * absOrientationB.v[2].z;
|
||||||
|
d += boundingOffsetB.z * absOrientationB.v[1].z;
|
||||||
|
if( ::Utility::Value::abs(orientationB.v[3].y*orientationB.v[0].x - orientationB.v[3].x*orientationB.v[0].y) > d ) return false;
|
||||||
|
|
||||||
|
// ( 0,0,1 ) x orientationB.v[1].xyz:
|
||||||
|
d = boundingOffsetA.x * absOrientationB.v[1].y;
|
||||||
|
d += boundingOffsetA.y * absOrientationB.v[1].x;
|
||||||
|
d += boundingOffsetB.x * absOrientationB.v[2].z;
|
||||||
|
d += boundingOffsetB.z * absOrientationB.v[0].z;
|
||||||
|
if( ::Utility::Value::abs(orientationB.v[3].y*orientationB.v[1].x - orientationB.v[3].x*orientationB.v[1].y) > d ) return false;
|
||||||
|
|
||||||
|
// ( 0,0,1 ) x orientationB.v[2].xyz:
|
||||||
|
d = boundingOffsetA.x * absOrientationB.v[2].y;
|
||||||
|
d += boundingOffsetA.y * absOrientationB.v[2].x;
|
||||||
|
d += boundingOffsetB.x * absOrientationB.v[1].z;
|
||||||
|
d += boundingOffsetB.y * absOrientationB.v[0].z;
|
||||||
|
if( ::Utility::Value::abs(orientationB.v[3].y*orientationB.v[2].x - orientationB.v[3].x*orientationB.v[2].y) > d ) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC BODY //////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void compare( Float &connectDistance, Float &connectOffsetSquared, const Ray &ray, const Point &point )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float3 dP = point.position - ray.origin;
|
||||||
|
|
||||||
|
connectDistance = dP.dot( ray.direction );
|
||||||
|
connectDistance /= ray.direction.dot( ray.direction );
|
||||||
|
|
||||||
|
dP -= ( connectDistance * ray.direction );
|
||||||
|
connectOffsetSquared = dP.dot( dP );
|
||||||
|
}
|
||||||
|
|
||||||
|
void compare( Float &connectDistanceA, Float &connectDistanceB, Float &connectOffsetSquared, const Ray &rayA, const Ray &rayB )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float3 dP = rayB.origin - rayA.origin;
|
||||||
|
connectDistanceA = rayA.direction.dot( dP );
|
||||||
|
connectDistanceA /= rayA.direction.dot( rayA.direction );
|
||||||
|
|
||||||
|
dP *= -1.0f;
|
||||||
|
connectDistanceB = rayB.direction.dot( dP );
|
||||||
|
connectDistanceB /= rayB.direction.dot( rayB.direction );
|
||||||
|
|
||||||
|
dP = rayA.direction * connectDistanceA;
|
||||||
|
dP += rayA.origin;
|
||||||
|
dP -= rayB.direction * connectDistanceB;
|
||||||
|
dP -= rayB.origin;
|
||||||
|
|
||||||
|
connectOffsetSquared = dP.dot( dP );
|
||||||
|
}
|
||||||
|
|
||||||
|
void compare( Float &connectOffset, const Plane &plane, const Point &point )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Private::compare( connectOffset, plane, point.position );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Point &pointA, const Point &pointB )
|
||||||
|
{ // by Fredrick Johansson
|
||||||
|
if (pointA.position.x != pointB.position.x) return false;
|
||||||
|
if (pointA.position.y != pointB.position.y) return false;
|
||||||
|
if (pointA.position.z != pointB.position.z) return false;
|
||||||
|
return true; // Passed all tests, is in same position
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Ray &ray, const Point &point, Float &connectDistance )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float connectOffsetSquared;
|
||||||
|
compare( connectDistance, connectOffsetSquared, ray, point );
|
||||||
|
|
||||||
|
if( Private::equalsZero(connectOffsetSquared) )
|
||||||
|
{
|
||||||
|
connectOffsetSquared = 0.0f;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
connectDistance = 0.0f;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Ray &rayA, const Ray &rayB, Float &connectDistanceA, Float &connectDistanceB )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float connectOffsetSquared;
|
||||||
|
compare( connectDistanceA, connectDistanceB, connectOffsetSquared, rayA, rayB );
|
||||||
|
|
||||||
|
if( Private::equalsZero(connectOffsetSquared) )
|
||||||
|
{
|
||||||
|
connectOffsetSquared = 0.0f;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
connectDistanceA = connectDistanceB = 0.0f;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Sphere &sphere, const Point &point )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float3 dP = point.position - sphere.center;
|
||||||
|
if( dP.dot(dP) > (sphere.radius * sphere.radius) )
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Sphere &sphere, const Ray &ray, Float &connectDistance )
|
||||||
|
{// by Dan Andersson
|
||||||
|
Float3 dP = sphere.center - ray.origin;
|
||||||
|
Float s = dP.dot( ray.direction ),
|
||||||
|
dSquared = dP.dot( dP ),
|
||||||
|
rSquared = sphere.radius * sphere.radius;
|
||||||
|
|
||||||
|
if( dSquared <= rSquared ) { connectDistance = 0.0f; return true; }
|
||||||
|
else if( s < 0.0f ) { connectDistance = 0.0f; return false; }
|
||||||
|
|
||||||
|
Float mSquared = dSquared - (s*s);
|
||||||
|
if( mSquared > rSquared ) { connectDistance = 0.0f; return false; }
|
||||||
|
|
||||||
|
Float q = ::std::sqrt( rSquared - mSquared );
|
||||||
|
if( dSquared > rSquared ) connectDistance = s - q;
|
||||||
|
else connectDistance = s + q;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Sphere &sphereA, const Sphere &sphereB )
|
||||||
|
{ // by Fredrick Johansson
|
||||||
|
Float3 C = sphereA.center;
|
||||||
|
C -= sphereB.center;
|
||||||
|
Float r = (sphereA.radius + sphereB.radius);
|
||||||
|
|
||||||
|
if (r*r >= C.dot(C))
|
||||||
|
{
|
||||||
|
return true; // Intersect detected!
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Plane &plane, const Point &point )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float connectOffset;
|
||||||
|
Private::compare( connectOffset, plane, point.position );
|
||||||
|
return Private::equalsZero(connectOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Plane &plane, const Ray &ray, Float &connectDistance )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float c = plane.normal.dot(ray.direction);
|
||||||
|
if( Private::equalsZero(c) )
|
||||||
|
{ // ray is parallell with the plane. (ray direction orthogonal with the planar normal)
|
||||||
|
connectDistance = 0.0f;
|
||||||
|
return contains( plane, ray.origin );
|
||||||
|
}
|
||||||
|
|
||||||
|
connectDistance = -plane.phasing;
|
||||||
|
connectDistance -= plane.normal.dot( ray.origin );
|
||||||
|
connectDistance /= c;
|
||||||
|
|
||||||
|
if( connectDistance > 0.0f )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
connectDistance = 0.0f;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Plane &plane, const Sphere &sphere )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float connectOffset;
|
||||||
|
Private::compare( connectOffset, plane, sphere.center );
|
||||||
|
return (connectOffset <= sphere.radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Plane &planeA, const Plane &planeB )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
if( planeA.normal == planeB.normal ) // they are parallell
|
||||||
|
return (planeA.phasing == planeB.phasing);
|
||||||
|
else if( planeA.normal == -planeB.normal ) // they are still parallell
|
||||||
|
return (planeA.phasing == -planeB.phasing);
|
||||||
|
return true; // none parallell planes ALWAYS intersects somewhere
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const BoxAxisAligned &box, const Point &point )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
if( point.position.x < box.minVertex.x ) return false;
|
||||||
|
if( point.position.x > box.maxVertex.x ) return false;
|
||||||
|
if( point.position.y < box.minVertex.y ) return false;
|
||||||
|
if( point.position.y > box.maxVertex.y ) return false;
|
||||||
|
if( point.position.z < box.minVertex.z ) return false;
|
||||||
|
if( point.position.z > box.maxVertex.z ) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const BoxAxisAligned &box, const Ray &ray, Float &connectDistance )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float tMin = ::std::numeric_limits<Float>::max(),
|
||||||
|
tMax = -tMin; // initiating to extremevalues
|
||||||
|
|
||||||
|
Float3 boundingOffset = ((box.maxVertex - box.minVertex) * 0.5f),
|
||||||
|
dP = ((box.maxVertex + box.minVertex) * 0.5f) - ray.origin;
|
||||||
|
if( Private::boxVsRayPerSlabCheck( Float3::standardUnitX, boundingOffset.x, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
|
||||||
|
if( Private::boxVsRayPerSlabCheck( Float3::standardUnitY, boundingOffset.y, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
|
||||||
|
if( Private::boxVsRayPerSlabCheck( Float3::standardUnitZ, boundingOffset.z, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
|
||||||
|
|
||||||
|
if( tMin > 0.0f ) connectDistance = tMin;
|
||||||
|
else connectDistance = tMax;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const BoxAxisAligned &box, const Sphere &sphere )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float3 e = ::Utility::Value::max( box.minVertex - sphere.center, Float3::null );
|
||||||
|
e += ::Utility::Value::max( sphere.center - box.maxVertex, Float3::null );
|
||||||
|
|
||||||
|
if( e.dot(e) > (sphere.radius * sphere.radius) ) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const BoxAxisAligned &box, const Plane &plane )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float e, d;
|
||||||
|
Private::compare( e, d, plane, box );
|
||||||
|
if( d - e > 0.0f ) return false; // is beneath
|
||||||
|
if( d + e < 0.0f ) return false; // is above
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bool intersect( const BoxAxisAligned &box, const Triangle &triangle )
|
||||||
|
// { return false; /* TODO */ }
|
||||||
|
|
||||||
|
bool intersect( const BoxAxisAligned &boxA, const BoxAxisAligned &boxB )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
if( boxA.maxVertex.x < boxB.minVertex.x ) return false;
|
||||||
|
if( boxA.minVertex.x > boxB.maxVertex.x ) return false;
|
||||||
|
if( boxA.maxVertex.y < boxB.minVertex.y ) return false;
|
||||||
|
if( boxA.minVertex.y > boxB.maxVertex.y ) return false;
|
||||||
|
if( boxA.maxVertex.z < boxB.minVertex.z ) return false;
|
||||||
|
if( boxA.minVertex.z > boxB.maxVertex.z ) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Box &box, const Point &point )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float3 dPos = point.position - box.orientation.v[3].xyz;
|
||||||
|
|
||||||
|
Float coordinate = dPos.dot( box.orientation.v[0].xyz );
|
||||||
|
if( coordinate > box.boundingOffset.x ) return false;
|
||||||
|
if( coordinate < -box.boundingOffset.x ) return false;
|
||||||
|
|
||||||
|
coordinate = dPos.dot( box.orientation.v[1].xyz );
|
||||||
|
if( coordinate > box.boundingOffset.y ) return false;
|
||||||
|
if( coordinate < -box.boundingOffset.y ) return false;
|
||||||
|
|
||||||
|
coordinate = dPos.dot( box.orientation.v[2].xyz );
|
||||||
|
if( coordinate > box.boundingOffset.z ) return false;
|
||||||
|
if( coordinate < -box.boundingOffset.z ) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Box &box, const Ray &ray, Float &connectDistance )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float tMin = ::std::numeric_limits<Float>::max(),
|
||||||
|
tMax = -tMin; // initiating to extremevalues
|
||||||
|
|
||||||
|
Float3 dP = box.center - ray.origin;
|
||||||
|
if( Private::boxVsRayPerSlabCheck( box.xAxis, box.boundingOffset.x, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
|
||||||
|
if( Private::boxVsRayPerSlabCheck( box.yAxis, box.boundingOffset.y, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
|
||||||
|
if( Private::boxVsRayPerSlabCheck( box.zAxis, box.boundingOffset.z, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
|
||||||
|
|
||||||
|
if( tMin > 0.0f ) connectDistance = tMin;
|
||||||
|
else connectDistance = tMax;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Box &box, const Sphere &sphere )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float3 e = sphere.center - box.orientation.v[3].xyz,
|
||||||
|
centerL = Float3( e.dot(box.orientation.v[0].xyz), e.dot(box.orientation.v[1].xyz), e.dot(box.orientation.v[2].xyz) );
|
||||||
|
|
||||||
|
e = ::Utility::Value::max( (box.boundingOffset + centerL)*=-1.0f, Float3::null );
|
||||||
|
e += ::Utility::Value::max( centerL - box.boundingOffset, Float3::null );
|
||||||
|
|
||||||
|
if( e.dot(e) > (sphere.radius * sphere.radius) ) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Box &box, const Plane &plane )
|
||||||
|
{// by Dan Andersson
|
||||||
|
Float e, d;
|
||||||
|
Private::compare( e, d, plane, box );
|
||||||
|
if( d - e > 0.0f ) return false; // is beneath
|
||||||
|
if( d + e < 0.0f ) return false; // is above
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Box &boxA, const BoxAxisAligned &boxB )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float3 alignedOffsetBoundaries = boxB.maxVertex - boxB.minVertex;
|
||||||
|
Float4x4 translated = boxA.orientation;
|
||||||
|
translated.v[3].xyz -= boxB.minVertex;
|
||||||
|
translated.v[3].xyz += alignedOffsetBoundaries * 0.5f;
|
||||||
|
alignedOffsetBoundaries = ::Utility::Value::abs(alignedOffsetBoundaries);
|
||||||
|
return Private::fifteenAxisVsAlignedAxisOverlappingChecks( alignedOffsetBoundaries, boxA.boundingOffset, translated );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Box &boxA, const Box &boxB )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float4x4 M;
|
||||||
|
inverseRigidBodyMatrix( M, boxA.orientation );
|
||||||
|
transformMatrix( M, boxB.orientation, M );
|
||||||
|
return Private::fifteenAxisVsAlignedAxisOverlappingChecks( boxA.boundingOffset, boxB.boundingOffset, M );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Frustrum &frustrum, const Point &point )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float connectOffset;
|
||||||
|
|
||||||
|
Private::compare( connectOffset, frustrum.leftPlane, point.position );
|
||||||
|
if( connectOffset < 0.0f ) return false;
|
||||||
|
|
||||||
|
Private::compare( connectOffset, frustrum.rightPlane, point.position );
|
||||||
|
if( connectOffset < 0.0f ) return false;
|
||||||
|
|
||||||
|
Private::compare( connectOffset, frustrum.bottomPlane, point.position );
|
||||||
|
if( connectOffset < 0.0f) return false;
|
||||||
|
|
||||||
|
Private::compare( connectOffset, frustrum.topPlane, point.position );
|
||||||
|
if( connectOffset < 0.0f) return false;
|
||||||
|
|
||||||
|
Private::compare( connectOffset, frustrum.nearPlane, point.position );
|
||||||
|
if( connectOffset < 0.0f ) return false;
|
||||||
|
|
||||||
|
Private::compare( connectOffset, frustrum.farPlane, point.position );
|
||||||
|
if( connectOffset < 0.0f ) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Frustrum &frustrum, const Ray &ray, Float &connectDistance )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
bool intersected = false;
|
||||||
|
Float distance = 0.0f;
|
||||||
|
connectDistance = ::std::numeric_limits<Float>::max();
|
||||||
|
|
||||||
|
if( intersect(frustrum.leftPlane, ray, distance) )
|
||||||
|
{
|
||||||
|
intersected = true;
|
||||||
|
connectDistance = ::Utility::Value::min( connectDistance, distance );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( intersect(frustrum.rightPlane, ray, distance) )
|
||||||
|
{
|
||||||
|
intersected = true;
|
||||||
|
connectDistance = ::Utility::Value::min( connectDistance, distance );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( intersect(frustrum.bottomPlane, ray, distance) )
|
||||||
|
{
|
||||||
|
intersected = true;
|
||||||
|
connectDistance = ::Utility::Value::min( connectDistance, distance );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( intersect(frustrum.topPlane, ray, distance) )
|
||||||
|
{
|
||||||
|
intersected = true;
|
||||||
|
connectDistance = ::Utility::Value::min( connectDistance, distance );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( intersect(frustrum.nearPlane, ray, distance) )
|
||||||
|
{
|
||||||
|
intersected = true;
|
||||||
|
connectDistance = ::Utility::Value::min( connectDistance, distance );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( intersect(frustrum.farPlane, ray, distance) )
|
||||||
|
{
|
||||||
|
intersected = true;
|
||||||
|
connectDistance = ::Utility::Value::min( connectDistance, distance );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( intersected ) return true;
|
||||||
|
|
||||||
|
connectDistance = 0.0f;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Frustrum &frustrum, const Sphere &sphere )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float connectOffset;
|
||||||
|
|
||||||
|
Private::compare( connectOffset, frustrum.leftPlane, sphere.center );
|
||||||
|
if( connectOffset < -sphere.radius ) return false;
|
||||||
|
|
||||||
|
Private::compare( connectOffset, frustrum.rightPlane, sphere.center );
|
||||||
|
if( connectOffset < -sphere.radius ) return false;
|
||||||
|
|
||||||
|
Private::compare( connectOffset, frustrum.bottomPlane, sphere.center );
|
||||||
|
if( connectOffset < -sphere.radius ) return false;
|
||||||
|
|
||||||
|
Private::compare( connectOffset, frustrum.topPlane, sphere.center );
|
||||||
|
if( connectOffset < -sphere.radius ) return false;
|
||||||
|
|
||||||
|
Private::compare( connectOffset, frustrum.nearPlane, sphere.center );
|
||||||
|
if( connectOffset < -sphere.radius ) return false;
|
||||||
|
|
||||||
|
Private::compare( connectOffset, frustrum.farPlane, sphere.center );
|
||||||
|
if( connectOffset < -sphere.radius ) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Frustrum &frustrum, const Plane &plane )
|
||||||
|
{
|
||||||
|
return false; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// bool intersect( const Frustrum &frustrum, const Triangle &triangle, ? );
|
||||||
|
|
||||||
|
bool intersect( const Frustrum &frustrum, const BoxAxisAligned &box )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float e, d;
|
||||||
|
|
||||||
|
Private::compare( e, d, frustrum.leftPlane, box );
|
||||||
|
if( d - e > 0.0f ) return false; // is beneath
|
||||||
|
|
||||||
|
Private::compare( e, d, frustrum.rightPlane, box );
|
||||||
|
if( d - e > 0.0f ) return false; // is beneath
|
||||||
|
|
||||||
|
Private::compare( e, d, frustrum.bottomPlane, box );
|
||||||
|
if( d - e > 0.0f ) return false; // is beneath
|
||||||
|
|
||||||
|
Private::compare( e, d, frustrum.topPlane, box );
|
||||||
|
if( d - e > 0.0f ) return false; // is beneath
|
||||||
|
|
||||||
|
Private::compare( e, d, frustrum.nearPlane, box );
|
||||||
|
if( d - e > 0.0f ) return false; // is beneath
|
||||||
|
|
||||||
|
Private::compare( e, d, frustrum.farPlane, box );
|
||||||
|
if( d - e > 0.0f ) return false; // is beneath
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Frustrum &frustrum, const Box &box )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
Float e, d;
|
||||||
|
|
||||||
|
Private::compare( e, d, frustrum.leftPlane, box );
|
||||||
|
if( d - e > 0.0f ) return false; // is beneath
|
||||||
|
|
||||||
|
Private::compare( e, d, frustrum.rightPlane, box );
|
||||||
|
if( d - e > 0.0f ) return false; // is beneath
|
||||||
|
|
||||||
|
Private::compare( e, d, frustrum.bottomPlane, box );
|
||||||
|
if( d - e > 0.0f ) return false; // is beneath
|
||||||
|
|
||||||
|
Private::compare( e, d, frustrum.topPlane, box );
|
||||||
|
if( d - e > 0.0f ) return false; // is beneath
|
||||||
|
|
||||||
|
Private::compare( e, d, frustrum.nearPlane, box );
|
||||||
|
if( d - e > 0.0f ) return false; // is beneath
|
||||||
|
|
||||||
|
Private::compare( e, d, frustrum.farPlane, box );
|
||||||
|
if( d - e > 0.0f ) return false; // is beneath
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect( const Frustrum &frustrumA, const Frustrum &frustrumB )
|
||||||
|
{
|
||||||
|
return false; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains( const Ray &container, const Ray &ray )
|
||||||
|
{
|
||||||
|
return false; /*TODO*/
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains( const Sphere &sphereA, const Sphere &sphereB )
|
||||||
|
{ // by Fredrick Johansson
|
||||||
|
// Check if SphereB is larger than sphereA
|
||||||
|
if (sphereA.radius < sphereB.radius)
|
||||||
|
{
|
||||||
|
return false; // Is impossible, yes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calc distance from center to center
|
||||||
|
Float3 d = sphereB.center - sphereA.center;
|
||||||
|
Float deltaR = sphereA.radius - sphereB.radius;
|
||||||
|
|
||||||
|
// Check if contained
|
||||||
|
if (d.dot(d) <= (deltaR*deltaR))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not contained
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains( const Plane &container, const Point &point )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
return Private::contains( container, point.position );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains( const Plane &container, const Ray &ray )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
if( Private::notEqualsZero(container.normal.dot(ray.direction)) ) return false;
|
||||||
|
return contains( container, ray.origin );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains( const Plane &container, const Plane &plane )
|
||||||
|
{ // by Dan Andersson
|
||||||
|
if( container.phasing == plane.phasing )
|
||||||
|
return container.normal == plane.normal;
|
||||||
|
if( container.phasing == -plane.phasing )
|
||||||
|
return container.normal == -plane.normal;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} } }
|
|
@ -0,0 +1,104 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef OYSTER_COLLISION_UTILITY_H
|
||||||
|
#define OYSTER_COLLISION_UTILITY_H
|
||||||
|
|
||||||
|
#include "ICollideable.h"
|
||||||
|
#include "Point.h"
|
||||||
|
#include "Ray.h"
|
||||||
|
#include "Sphere.h"
|
||||||
|
#include "Plane.h"
|
||||||
|
//#include "Triangle.h"
|
||||||
|
#include "BoxAxisAligned.h"
|
||||||
|
#include "Box.h"
|
||||||
|
#include "Frustrum.h"
|
||||||
|
|
||||||
|
namespace Oyster { namespace Collision { namespace Utility
|
||||||
|
{
|
||||||
|
void compare( ::Oyster::Math::Float &connectDistance, ::Oyster::Math::Float &connectOffsetSquared, const Ray &ray, const Point &point );
|
||||||
|
void compare( ::Oyster::Math::Float &connectDistanceA, ::Oyster::Math::Float &connectDistanceB, ::Oyster::Math::Float &connectOffsetSquared, const Ray &rayA, const Ray &rayB );
|
||||||
|
void compare( ::Oyster::Math::Float &connectOffset, const Plane &plane, const Point &point );
|
||||||
|
|
||||||
|
bool intersect( const Point &pointA, const Point &pointB );
|
||||||
|
|
||||||
|
bool intersect( const Ray &ray, const Point &point, ::Oyster::Math::Float &connectDistance );
|
||||||
|
bool intersect( const Ray &rayA, const Ray &rayB, ::Oyster::Math::Float &connectDistanceA, ::Oyster::Math::Float &connectDistanceB );
|
||||||
|
|
||||||
|
bool intersect( const Sphere &sphere, const Point &point );
|
||||||
|
bool intersect( const Sphere &sphere, const Ray &ray, ::Oyster::Math::Float &connectDistance );
|
||||||
|
bool intersect( const Sphere &sphereA, const Sphere &sphereB );
|
||||||
|
|
||||||
|
bool intersect( const Plane &plane, const Point &point );
|
||||||
|
bool intersect( const Plane &plane, const Ray &ray, ::Oyster::Math::Float &connectDistance );
|
||||||
|
bool intersect( const Plane &plane, const Sphere &sphere );
|
||||||
|
bool intersect( const Plane &planeA, const Plane &planeB );
|
||||||
|
|
||||||
|
// bool intersect( const Triangle &triangle, const Point &point, ? );
|
||||||
|
// bool intersect( const Triangle &triangle, const Ray &ray, ? );
|
||||||
|
// bool intersect( const Triangle &triangle, const Sphere &sphere, ? );
|
||||||
|
// bool intersect( const Triangle &triangle, const Plane &plane, ? );
|
||||||
|
// bool intersect( const Triangle &triangleA, const Triangle &triangleB, ? );
|
||||||
|
|
||||||
|
bool intersect( const BoxAxisAligned &box, const Point &point );
|
||||||
|
bool intersect( const BoxAxisAligned &box, const Ray &ray, ::Oyster::Math::Float &connectDistance );
|
||||||
|
bool intersect( const BoxAxisAligned &box, const Sphere &sphere );
|
||||||
|
bool intersect( const BoxAxisAligned &box, const Plane &plane );
|
||||||
|
// bool intersect( const BoxAxisAligned &box, const Triangle &triangle );
|
||||||
|
bool intersect( const BoxAxisAligned &boxA, const BoxAxisAligned &boxB );
|
||||||
|
|
||||||
|
bool intersect( const Box &box, const Point &point );
|
||||||
|
bool intersect( const Box &box, const Ray &ray, ::Oyster::Math::Float &connectDistance );
|
||||||
|
bool intersect( const Box &box, const Sphere &sphere );
|
||||||
|
bool intersect( const Box &box, const Plane &plane );
|
||||||
|
// bool intersect( const Box &box, const Triangle &triangle, ? );
|
||||||
|
bool intersect( const Box &boxA, const BoxAxisAligned &boxB );
|
||||||
|
bool intersect( const Box &boxA, const Box &boxB );
|
||||||
|
|
||||||
|
bool intersect( const Frustrum &frustrum, const Point &point );
|
||||||
|
bool intersect( const Frustrum &frustrum, const Ray &ray, ::Oyster::Math::Float &connectDistance );
|
||||||
|
bool intersect( const Frustrum &frustrum, const Sphere &sphere );
|
||||||
|
bool intersect( const Frustrum &frustrum, const Plane &plane );
|
||||||
|
// bool intersect( const Frustrum &frustrum, const Triangle &triangle, ? );
|
||||||
|
bool intersect( const Frustrum &frustrum, const BoxAxisAligned &box );
|
||||||
|
bool intersect( const Frustrum &frustrum, const Box &box );
|
||||||
|
bool intersect( const Frustrum &frustrumA, const Frustrum &frustrumB );
|
||||||
|
|
||||||
|
bool contains( const Ray &container, const Ray &ray );
|
||||||
|
|
||||||
|
bool contains( const Sphere &container, const Sphere &sphere );
|
||||||
|
// bool contains( const Sphere &container, const Triangle &triangle );
|
||||||
|
// bool contains( const Sphere &container, const BoxAxisAligned &box );
|
||||||
|
// bool contains( const Sphere &container, const Box &box );
|
||||||
|
// bool contains( const Sphere &container, const Frustrum &frustrum );
|
||||||
|
|
||||||
|
bool contains( const Plane &container, const Point &point );
|
||||||
|
bool contains( const Plane &container, const Ray &ray );
|
||||||
|
bool contains( const Plane &container, const Plane &plane );
|
||||||
|
// bool contains( const Plane &container, const Triangle &triangle );
|
||||||
|
|
||||||
|
// bool contains( const Triangle &container, const Point &point );
|
||||||
|
// bool contains( const Triangle &container, const Triangle &triangle );
|
||||||
|
|
||||||
|
// bool contains( const BoxAxisAligned &container, const Sphere &sphere );
|
||||||
|
// bool contains( const BoxAxisAligned &container, const Triangle &triangle );
|
||||||
|
// bool contains( const BoxAxisAligned &container, const BoxAxisAligned &box );
|
||||||
|
// bool contains( const BoxAxisAligned &container, const Box &box );
|
||||||
|
// bool contains( const BoxAxisAligned &container, const Frustrum &frustrum );
|
||||||
|
|
||||||
|
// bool contains( const Box &container, const Sphere &sphere );
|
||||||
|
// bool contains( const Box &container, const Triangle &triangle );
|
||||||
|
// bool contains( const Box &container, const BoxAxisAligned &box );
|
||||||
|
// bool contains( const Box &container, const Box &box );
|
||||||
|
// bool contains( const Box &container, const Frustrum &frustrum );
|
||||||
|
|
||||||
|
// bool contains( const Frustrum &container, const Sphere &sphere );
|
||||||
|
// bool contains( const Frustrum &container, const Triangle &triangle );
|
||||||
|
// bool contains( const Frustrum &container, const BoxAxisAligned &box );
|
||||||
|
// bool contains( const Frustrum &container, const Box &box );
|
||||||
|
// bool contains( const Frustrum &container, const Frustrum &frustrum );
|
||||||
|
} } }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,234 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "Frustrum.h"
|
||||||
|
#include "Collision.h"
|
||||||
|
|
||||||
|
using namespace Oyster::Math;
|
||||||
|
using namespace Oyster::Collision;
|
||||||
|
|
||||||
|
namespace PrivateStatic
|
||||||
|
{
|
||||||
|
inline void vpToPlanes( Plane &lp, Plane &rp, Plane &bp, Plane &tp, Plane &np, Plane &fp, const Float4x4 &vp )
|
||||||
|
{
|
||||||
|
Float4x4 m = vp.getTranspose();
|
||||||
|
|
||||||
|
// left
|
||||||
|
lp.normal = m.v[3].xyz + m.v[0].xyz;
|
||||||
|
lp.phasing = lp.normal.length();
|
||||||
|
lp.normal /= lp.phasing;
|
||||||
|
lp.phasing = (m.v[3].w + m.v[0].w) / lp.phasing;
|
||||||
|
|
||||||
|
// right
|
||||||
|
rp.normal = m.v[3].xyz - m.v[0].xyz;
|
||||||
|
rp.phasing = rp.normal.length();
|
||||||
|
rp.normal /= rp.phasing;
|
||||||
|
rp.phasing = (m.v[3].w - m.v[0].w) / rp.phasing;
|
||||||
|
|
||||||
|
// bottom
|
||||||
|
bp.normal = m.v[3].xyz + m.v[1].xyz;
|
||||||
|
bp.phasing = bp.normal.length();
|
||||||
|
bp.normal /= bp.phasing;
|
||||||
|
bp.phasing = (m.v[3].w + m.v[1].w) / bp.phasing;
|
||||||
|
|
||||||
|
// top
|
||||||
|
tp.normal = m.v[3].xyz - m.v[1].xyz;
|
||||||
|
tp.phasing = tp.normal.length();
|
||||||
|
tp.normal /= tp.phasing;
|
||||||
|
tp.phasing = (m.v[3].w - m.v[1].w) / tp.phasing;
|
||||||
|
|
||||||
|
// near leftHanded DirectX
|
||||||
|
np.normal = m.v[2].xyz;
|
||||||
|
np.phasing = np.normal.length();
|
||||||
|
np.normal /= np.phasing;
|
||||||
|
np.phasing = m.v[2].w / np.phasing;
|
||||||
|
|
||||||
|
// far lefthanded
|
||||||
|
fp.normal = m.v[3].xyz - m.v[2].xyz;
|
||||||
|
fp.phasing = fp.normal.length();
|
||||||
|
fp.normal /= fp.phasing;
|
||||||
|
fp.phasing = (m.v[3].w - m.v[2].w) / fp.phasing;
|
||||||
|
|
||||||
|
/*/ near rightHanded openGL
|
||||||
|
np.normal = m.v[3].xyz + m.v[2].xyz;
|
||||||
|
np.phasing = np.normal.length();
|
||||||
|
np.normal /= np.phasing;
|
||||||
|
np.phasing = -(m.v[3].w + m.v[2].w) / np.phasing;
|
||||||
|
|
||||||
|
// far rightHanded
|
||||||
|
fp.normal = m.v[3].xyz - m.v[2].xyz;
|
||||||
|
fp.phasing = fp.normal.length();
|
||||||
|
fp.normal /= fp.phasing;
|
||||||
|
fp.phasing = -(m.v[3].w - m.v[2].w) / fp.phasing;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void interpolatePlanes( Plane &target, const Plane &planeA, const Plane &planeB, float interpolation )
|
||||||
|
{
|
||||||
|
float counterInterpol = 1.0f - interpolation;
|
||||||
|
target.normal = counterInterpol * planeA.normal;
|
||||||
|
target.normal += interpolation * planeB.normal;
|
||||||
|
target.phasing = counterInterpol * planeA.phasing;
|
||||||
|
target.phasing += interpolation * planeB.phasing;
|
||||||
|
target.normal.normalize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Frustrum::Frustrum( ) : ICollideable(ICollideable::Frustrum),
|
||||||
|
leftPlane(Float3::standardUnitX, -0.5f), rightPlane(-Float3::standardUnitX, 0.5f),
|
||||||
|
bottomPlane(Float3::standardUnitY, -0.5f), topPlane(-Float3::standardUnitY, 0.5f),
|
||||||
|
nearPlane(Float3::standardUnitZ, -0.5f), farPlane(-Float3::standardUnitZ, 0.5f) {}
|
||||||
|
|
||||||
|
Frustrum::Frustrum( const Frustrum &frustrum ) : ICollideable(ICollideable::Frustrum),
|
||||||
|
leftPlane(frustrum.leftPlane), rightPlane(frustrum.rightPlane),
|
||||||
|
bottomPlane(frustrum.bottomPlane), topPlane(frustrum.topPlane),
|
||||||
|
nearPlane(frustrum.nearPlane), farPlane(frustrum.farPlane) {}
|
||||||
|
|
||||||
|
Frustrum::Frustrum( const Float4x4 &vp ) : ICollideable(ICollideable::Frustrum)
|
||||||
|
{ PrivateStatic::vpToPlanes( this->leftPlane, this->rightPlane, this->bottomPlane, this->topPlane, this->nearPlane, this->farPlane, vp ); }
|
||||||
|
|
||||||
|
Frustrum::~Frustrum( ) {}
|
||||||
|
|
||||||
|
Frustrum & Frustrum::operator = ( const Frustrum &frustrum )
|
||||||
|
{
|
||||||
|
this->leftPlane = frustrum.leftPlane;
|
||||||
|
this->rightPlane = frustrum.rightPlane;
|
||||||
|
this->bottomPlane = frustrum.bottomPlane;
|
||||||
|
this->topPlane = frustrum.topPlane;
|
||||||
|
this->nearPlane = frustrum.nearPlane;
|
||||||
|
this->farPlane = frustrum.farPlane;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Frustrum & Frustrum::operator = ( const Float4x4 &vp )
|
||||||
|
{
|
||||||
|
PrivateStatic::vpToPlanes( this->leftPlane, this->rightPlane, this->bottomPlane, this->topPlane, this->nearPlane, this->farPlane, vp );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Frustrum::split( Frustrum target[], unsigned int numX, unsigned int numY, unsigned int numZ ) const
|
||||||
|
{
|
||||||
|
float incrementX = 1.0f / numX,
|
||||||
|
incrementY = 1.0f / numY,
|
||||||
|
incrementZ = 1.0f / numZ,
|
||||||
|
interpolX = 0.0f,
|
||||||
|
interpolY = 0.0f,
|
||||||
|
interpolZ = 0.0f;
|
||||||
|
|
||||||
|
unsigned int i = 0U,
|
||||||
|
stepY = numX,
|
||||||
|
stepZ = numX * numY;
|
||||||
|
|
||||||
|
Collision::Plane invRight( -this->rightPlane.normal, -this->rightPlane.phasing ),
|
||||||
|
invBottom( -this->bottomPlane.normal, -this->bottomPlane.phasing ),
|
||||||
|
invFar( -this->farPlane.normal, -this->farPlane.phasing );
|
||||||
|
|
||||||
|
for( unsigned int iz = 0U; iz < numZ; ++iz )
|
||||||
|
{
|
||||||
|
interpolY = 0.0f;
|
||||||
|
for( unsigned int iy = 0U; iy < numY; ++iy )
|
||||||
|
{
|
||||||
|
interpolX = 0.0f;
|
||||||
|
for( unsigned int ix = 0U; ix < numX; ++ix )
|
||||||
|
{
|
||||||
|
if( ix == 0 )
|
||||||
|
target[i].leftPlane = this->leftPlane;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrivateStatic::interpolatePlanes( target[i].leftPlane, this->leftPlane, invRight, interpolX );
|
||||||
|
|
||||||
|
unsigned int iLeft = i - 1;
|
||||||
|
target[iLeft].rightPlane.normal = -target[i].leftPlane.normal;
|
||||||
|
target[iLeft].rightPlane.phasing = -target[i].leftPlane.phasing;
|
||||||
|
}
|
||||||
|
if( ix == numX - 1 )
|
||||||
|
target[i].rightPlane = this->rightPlane;
|
||||||
|
|
||||||
|
if( iy == 0 )
|
||||||
|
target[i].topPlane = this->topPlane;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrivateStatic::interpolatePlanes( target[i].topPlane, this->topPlane, invBottom, interpolY );
|
||||||
|
|
||||||
|
unsigned int iAbove = i - stepY;
|
||||||
|
target[iAbove].bottomPlane.normal = -target[i].topPlane.normal;
|
||||||
|
target[iAbove].bottomPlane.phasing = -target[i].topPlane.phasing;
|
||||||
|
}
|
||||||
|
if( iy == numY - 1 )
|
||||||
|
target[i].bottomPlane = this->bottomPlane;
|
||||||
|
|
||||||
|
if( iz == 0 )
|
||||||
|
target[i].nearPlane = this->nearPlane;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrivateStatic::interpolatePlanes( target[i].nearPlane, this->nearPlane, invFar, interpolZ );
|
||||||
|
|
||||||
|
unsigned int iCloser = i - stepZ;
|
||||||
|
target[iCloser].farPlane.normal = -target[i].nearPlane.normal;
|
||||||
|
target[iCloser].farPlane.phasing = -target[i].nearPlane.phasing;
|
||||||
|
}
|
||||||
|
if( iz == numZ - 1 )
|
||||||
|
target[i].farPlane = this->farPlane;
|
||||||
|
|
||||||
|
++i;
|
||||||
|
interpolX += incrementX;
|
||||||
|
}
|
||||||
|
interpolY += incrementY;
|
||||||
|
}
|
||||||
|
interpolZ += incrementZ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Frustrum::writeToByte( unsigned char targetMem[], unsigned int &nextIndex ) const
|
||||||
|
{
|
||||||
|
Float *fMem = (Float*)&targetMem[nextIndex];
|
||||||
|
for( int p = 0; p < 6; ++p )
|
||||||
|
{
|
||||||
|
fMem[0] = this->plane[p].element[0];
|
||||||
|
fMem[1] = this->plane[p].element[1];
|
||||||
|
fMem[2] = this->plane[p].element[2];
|
||||||
|
fMem[3] = this->plane[p].element[3];
|
||||||
|
fMem = &fMem[4];
|
||||||
|
}
|
||||||
|
nextIndex += 6 * ::Utility::StaticArray::numElementsOf( this->plane[0].byte );
|
||||||
|
}
|
||||||
|
|
||||||
|
ICollideable* Frustrum::clone( ) const
|
||||||
|
{ return new Frustrum(*this); }
|
||||||
|
|
||||||
|
bool Frustrum::Intersects( const ICollideable *target ) const
|
||||||
|
{
|
||||||
|
switch( target->type )
|
||||||
|
{
|
||||||
|
case ICollideable::Point: return Utility::intersect( *this, *(Collision::Point*)target );
|
||||||
|
case ICollideable::Ray: return Utility::intersect( *this, *(Collision::Ray*)target, ((Collision::Ray*)target)->collisionDistance );
|
||||||
|
case ICollideable::Sphere: return Utility::intersect( *this, *(Collision::Sphere*)target );
|
||||||
|
case ICollideable::Plane: return Utility::intersect( *this, *(Collision::Plane*)target );
|
||||||
|
case ICollideable::Triangle: return false; // TODO
|
||||||
|
case ICollideable::BoxAxisAligned: return Utility::intersect( *this, *(Collision::BoxAxisAligned*)target );
|
||||||
|
case ICollideable::Box: return Utility::intersect( *this, *(Collision::Box*)target );
|
||||||
|
case ICollideable::Frustrum: return Utility::intersect( *this, *(Collision::Frustrum*)target );
|
||||||
|
case ICollideable::Line: return false; // TODO
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Frustrum::Contains( const ICollideable *target ) const
|
||||||
|
{
|
||||||
|
switch( target->type )
|
||||||
|
{
|
||||||
|
case ICollideable::Point: return Utility::intersect( *this, *(Collision::Point*)target );
|
||||||
|
case ICollideable::Ray: return false; // TODO
|
||||||
|
case ICollideable::Sphere: return false; // TODO
|
||||||
|
case ICollideable::Plane: return false; // TODO
|
||||||
|
case ICollideable::Triangle: return false; // TODO
|
||||||
|
case ICollideable::BoxAxisAligned: return false; // TODO
|
||||||
|
case ICollideable::Box: return false; // TODO
|
||||||
|
case ICollideable::Frustrum: return false; // TODO
|
||||||
|
case ICollideable::Line: return false; // TODO
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ICollideable::State Frustrum::Advanced( const ICollideable *target ) const
|
||||||
|
{ return ICollideable::Missed; } //Not supported returns 0
|
|
@ -0,0 +1,45 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef OYSTER_COLLISION_FRUSTRUM_H
|
||||||
|
#define OYSTER_COLLISION_FRUSTRUM_H
|
||||||
|
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "ICollideable.h"
|
||||||
|
#include "Plane.h"
|
||||||
|
|
||||||
|
namespace Oyster { namespace Collision
|
||||||
|
{
|
||||||
|
|
||||||
|
class Frustrum : public ICollideable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct{ class Plane plane[6]; };
|
||||||
|
struct
|
||||||
|
{ class Plane leftPlane, rightPlane, bottomPlane, topPlane, nearPlane, farPlane; };
|
||||||
|
};
|
||||||
|
|
||||||
|
Frustrum( );
|
||||||
|
Frustrum( const Frustrum &frustrum );
|
||||||
|
Frustrum( const ::Oyster::Math::Float4x4 &viewProjection );
|
||||||
|
~Frustrum( );
|
||||||
|
|
||||||
|
Frustrum & operator = ( const Frustrum &frustrum );
|
||||||
|
Frustrum & operator = ( const ::Oyster::Math::Float4x4 &viewProjection );
|
||||||
|
|
||||||
|
void split( Frustrum targetList[], unsigned int numX, unsigned int numY = 1U, unsigned int numZ = 1u ) const;
|
||||||
|
void writeToByte( unsigned char targetMem[], unsigned int &nextIndex ) const;
|
||||||
|
|
||||||
|
ICollideable* clone( ) const;
|
||||||
|
bool Intersects( const ICollideable *target ) const;
|
||||||
|
bool Contains( const ICollideable *target ) const;
|
||||||
|
ICollideable::State Advanced( const ICollideable *target ) const; //Not supported returns 0;
|
||||||
|
};
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,49 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Pär Hammarstrand 2013
|
||||||
|
// Edited by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef OYSTER_COLLISION_ICOLLIDEABLE_H
|
||||||
|
#define OYSTER_COLLISION_ICOLLIDEABLE_H
|
||||||
|
|
||||||
|
namespace Oyster { namespace Collision
|
||||||
|
{
|
||||||
|
class ICollideable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum CollisionType
|
||||||
|
{
|
||||||
|
Point,
|
||||||
|
Ray,
|
||||||
|
Sphere,
|
||||||
|
Plane,
|
||||||
|
Triangle,
|
||||||
|
BoxAxisAligned,
|
||||||
|
Box,
|
||||||
|
Frustrum,
|
||||||
|
Line
|
||||||
|
};
|
||||||
|
|
||||||
|
enum State
|
||||||
|
{
|
||||||
|
Missed = 0,
|
||||||
|
Contained,
|
||||||
|
Intersected
|
||||||
|
};
|
||||||
|
|
||||||
|
ICollideable( CollisionType _type ) : type(_type) {};
|
||||||
|
|
||||||
|
const CollisionType type;
|
||||||
|
|
||||||
|
virtual ICollideable* clone( ) const = 0;
|
||||||
|
|
||||||
|
virtual bool Intersects( const ICollideable *target ) const = 0;
|
||||||
|
|
||||||
|
virtual bool Contains( const ICollideable *target ) const = 0;
|
||||||
|
|
||||||
|
//Not supported returns 0;
|
||||||
|
virtual State Advanced( const ICollideable *target ) const = 0;
|
||||||
|
};
|
||||||
|
} }
|
||||||
|
#endif
|
|
@ -0,0 +1,40 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "Line.h"
|
||||||
|
#include "Collision.h"
|
||||||
|
|
||||||
|
using namespace ::Oyster::Collision;
|
||||||
|
using namespace ::Oyster::Math;
|
||||||
|
|
||||||
|
Line::Line( ) : ICollideable(ICollideable::Line), ray(), length(0.0f) {}
|
||||||
|
Line::Line( const Line &_line ) : ICollideable(ICollideable::Line), ray(_line.ray), length(_line.length) {}
|
||||||
|
Line::Line( const class Ray &_ray, const Float &_length ) : ICollideable(ICollideable::Line), ray(_ray), length(_length) {}
|
||||||
|
Line::Line( const Float3 &origin, const Float3 &normalizedDirection, const Float &_length ) : ICollideable(ICollideable::Line), ray(origin, normalizedDirection), length(_length) {}
|
||||||
|
Line::~Line( ) { /*Nothing needs to be done here*/ }
|
||||||
|
|
||||||
|
Line & Line::operator = ( const Line &line )
|
||||||
|
{
|
||||||
|
this->ray = line.ray;
|
||||||
|
this->length = line.length;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ICollideable* Line::clone( ) const
|
||||||
|
{ return new Line(*this); }
|
||||||
|
|
||||||
|
bool Line::Intersects( const ICollideable *target ) const
|
||||||
|
{
|
||||||
|
if( this->ray.Intersects( target ) ) if( this->ray.collisionDistance >= 0.0f ) if( this->ray.collisionDistance <= this->length )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
this->ray.collisionDistance = 0.0f;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Line::Contains( const ICollideable *target ) const
|
||||||
|
{ /*TODO*/ return false; }
|
||||||
|
|
||||||
|
ICollideable::State Line::Advanced( const ICollideable *target ) const
|
||||||
|
{ return ICollideable::Missed; } //Not supported returns 0
|
|
@ -0,0 +1,39 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef OYSTER_COLLISION_LINE_H
|
||||||
|
#define OYSTER_COLLISION_LINE_H
|
||||||
|
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "ICollideable.h"
|
||||||
|
#include "Ray.h"
|
||||||
|
|
||||||
|
namespace Oyster { namespace Collision
|
||||||
|
{
|
||||||
|
class Line : public ICollideable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct { class Ray ray; ::Oyster::Math::Float length; };
|
||||||
|
char byte[sizeof(class Ray) + sizeof(::Oyster::Math::Float)];
|
||||||
|
};
|
||||||
|
|
||||||
|
Line( );
|
||||||
|
Line( const Line &line );
|
||||||
|
Line( const class Ray &ray, const ::Oyster::Math::Float &length );
|
||||||
|
Line( const ::Oyster::Math::Float3 &origin, const ::Oyster::Math::Float3 &normalizedDirection, const ::Oyster::Math::Float &length );
|
||||||
|
~Line( );
|
||||||
|
|
||||||
|
Line & operator = ( const Line &line );
|
||||||
|
|
||||||
|
ICollideable* clone( ) const;
|
||||||
|
bool Intersects( const ICollideable *target ) const;
|
||||||
|
bool Contains( const ICollideable *target ) const;
|
||||||
|
ICollideable::State Advanced( const ICollideable *target ) const; //Not supported returns 0;
|
||||||
|
};
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,11 @@
|
||||||
|
#include "ICollideable.h"
|
||||||
|
#include "Point.h"
|
||||||
|
#include "Ray.h"
|
||||||
|
#include "Plane.h"
|
||||||
|
#include "Sphere.h"
|
||||||
|
#include "BoxAxisAligned.h"
|
||||||
|
#include "Box.h"
|
||||||
|
#include "Frustrum.h"
|
||||||
|
#include "Line.h"
|
||||||
|
|
||||||
|
#include "Collision.h"
|
|
@ -0,0 +1,56 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "Plane.h"
|
||||||
|
#include "Collision.h"
|
||||||
|
|
||||||
|
using namespace ::Oyster::Collision;
|
||||||
|
using namespace ::Oyster::Math;
|
||||||
|
|
||||||
|
Plane::Plane( ) : ICollideable(ICollideable::Plane), normal(), phasing(0.0f) {}
|
||||||
|
Plane::Plane( const Plane &plane ) : ICollideable(ICollideable::Plane), normal(plane.normal), phasing(plane.phasing) {}
|
||||||
|
Plane::Plane( const Float3 &n, const Float &p ) : ICollideable(ICollideable::Plane), normal(n), phasing(p) {}
|
||||||
|
Plane::~Plane( ) { /*Nothing needs to be done here*/ }
|
||||||
|
|
||||||
|
Plane & Plane::operator = ( const Plane &plane )
|
||||||
|
{
|
||||||
|
this->normal = plane.normal;
|
||||||
|
this->phasing = plane.phasing;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ICollideable* Plane::clone( ) const
|
||||||
|
{ return new Plane( *this ); }
|
||||||
|
|
||||||
|
bool Plane::Intersects( const ICollideable *target ) const
|
||||||
|
{
|
||||||
|
switch( target->type )
|
||||||
|
{
|
||||||
|
case ICollideable::Point: return Utility::intersect( *this, *(Collision::Point*)target );
|
||||||
|
case ICollideable::Ray: return Utility::intersect( *this, *(Collision::Ray*)target, ((Collision::Ray*)target)->collisionDistance );
|
||||||
|
case ICollideable::Sphere: return Utility::intersect( *this, *(Collision::Sphere*)target );
|
||||||
|
case ICollideable::Plane: return Utility::intersect( *this, *(Collision::Plane*)target );
|
||||||
|
case ICollideable::Triangle: return false; // TODO
|
||||||
|
case ICollideable::BoxAxisAligned: return Utility::intersect( *(Collision::BoxAxisAligned*)target, *this );
|
||||||
|
case ICollideable::Box: return Utility::intersect( *(Collision::Box*)target, *this );
|
||||||
|
case ICollideable::Frustrum: return false; // TODO
|
||||||
|
case ICollideable::Line: return false; // TODO
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Plane::Contains( const ICollideable *target ) const
|
||||||
|
{
|
||||||
|
switch( target->type )
|
||||||
|
{
|
||||||
|
case ICollideable::Point: return Utility::intersect( *this, *(Collision::Point*)target );
|
||||||
|
case ICollideable::Ray: return Utility::contains( *this, *(Collision::Ray*)target );
|
||||||
|
case ICollideable::Plane: return Utility::contains( *this, *(Collision::Plane*)target );
|
||||||
|
case ICollideable::Triangle: return false; // TODO
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ICollideable::State Plane::Advanced( const ICollideable *target ) const
|
||||||
|
{ return ICollideable::Missed; } //Not supported returns 0
|
|
@ -0,0 +1,38 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef OYSTER_COLLISION_PLANE_H
|
||||||
|
#define OYSTER_COLLISION_PLANE_H
|
||||||
|
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "ICollideable.h"
|
||||||
|
|
||||||
|
namespace Oyster { namespace Collision
|
||||||
|
{
|
||||||
|
class Plane : public ICollideable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct{ ::Oyster::Math::Float3 normal; ::Oyster::Math::Float phasing; };
|
||||||
|
::Oyster::Math::Float element[4];
|
||||||
|
char byte[sizeof(::Oyster::Math::Float3) + sizeof(::Oyster::Math::Float)];
|
||||||
|
};
|
||||||
|
|
||||||
|
Plane( );
|
||||||
|
Plane( const Plane &plane );
|
||||||
|
Plane( const ::Oyster::Math::Float3 &normal, const ::Oyster::Math::Float &phasing );
|
||||||
|
~Plane( );
|
||||||
|
|
||||||
|
Plane & operator = ( const Plane &plane );
|
||||||
|
|
||||||
|
ICollideable* clone( ) const;
|
||||||
|
bool Intersects( const ICollideable *target ) const;
|
||||||
|
bool Contains( const ICollideable *target ) const;
|
||||||
|
ICollideable::State Advanced( const ICollideable *target ) const; //Not supported returns 0;
|
||||||
|
};
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,51 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "Point.h"
|
||||||
|
#include "Collision.h"
|
||||||
|
|
||||||
|
using namespace ::Oyster::Collision;
|
||||||
|
using namespace ::Oyster::Math;
|
||||||
|
|
||||||
|
Point::Point( ) : ICollideable(ICollideable::Point), position() {}
|
||||||
|
Point::Point( const Point &point ) : ICollideable(ICollideable::Point), position(point.position) {}
|
||||||
|
Point::Point( const Float3 &pos ) : ICollideable(ICollideable::Point), position(pos) {}
|
||||||
|
Point::~Point( ) { /*Nothing needs to be done here*/ }
|
||||||
|
|
||||||
|
Point & Point::operator = ( const Point &point )
|
||||||
|
{
|
||||||
|
this->position = point.position;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ICollideable* Point::clone( ) const
|
||||||
|
{ return new Point( *this ); }
|
||||||
|
|
||||||
|
bool Point::Intersects( const ICollideable *target ) const
|
||||||
|
{
|
||||||
|
switch( target->type )
|
||||||
|
{
|
||||||
|
case ICollideable::Point: return Utility::intersect( *this, *(Collision::Point*)target );
|
||||||
|
case ICollideable::Ray: return Utility::intersect( *(Collision::Ray*)target, *this, ((Collision::Ray*)target)->collisionDistance );
|
||||||
|
case ICollideable::Sphere: Utility::intersect( *(Collision::Sphere*)target, *this );
|
||||||
|
case ICollideable::Plane: return Utility::intersect( *(Collision::Plane*)target, *this );
|
||||||
|
case ICollideable::Triangle: return false; // TODO
|
||||||
|
case ICollideable::BoxAxisAligned: return Utility::intersect( *(Collision::BoxAxisAligned*)target, *this );
|
||||||
|
case ICollideable::Box: return Utility::intersect( *(Collision::Box*)target, *this );
|
||||||
|
case ICollideable::Frustrum: return false; // TODO
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Point::Contains( const ICollideable *target ) const
|
||||||
|
{
|
||||||
|
switch( target->type )
|
||||||
|
{
|
||||||
|
case ICollideable::Point: return Utility::intersect( *this, *(Collision::Point*)target );
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ICollideable::State Point::Advanced( const ICollideable *target ) const
|
||||||
|
{ return ICollideable::Missed; } //Not supported returns 0
|
|
@ -0,0 +1,37 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef OYSTER_COLLISION_POINT_H
|
||||||
|
#define OYSTER_COLLISION_POINT_H
|
||||||
|
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "ICollideable.h"
|
||||||
|
|
||||||
|
namespace Oyster { namespace Collision
|
||||||
|
{
|
||||||
|
class Point : public ICollideable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct{ ::Oyster::Math::Float3 position; };
|
||||||
|
char byte[sizeof(::Oyster::Math::Float3)];
|
||||||
|
};
|
||||||
|
|
||||||
|
Point( );
|
||||||
|
Point( const Point &point );
|
||||||
|
Point( const ::Oyster::Math::Float3 &position );
|
||||||
|
~Point( );
|
||||||
|
|
||||||
|
Point & operator = ( const Point &point );
|
||||||
|
|
||||||
|
ICollideable* clone( ) const;
|
||||||
|
bool Intersects( const ICollideable *target ) const;
|
||||||
|
bool Contains( const ICollideable *target ) const;
|
||||||
|
ICollideable::State Advanced( const ICollideable *target ) const; //Not supported returns 0;
|
||||||
|
};
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,54 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "Ray.h"
|
||||||
|
#include "Collision.h"
|
||||||
|
|
||||||
|
using namespace ::Oyster::Collision;
|
||||||
|
using namespace ::Oyster::Math;
|
||||||
|
|
||||||
|
Ray::Ray( ) : ICollideable(ICollideable::Ray), origin(), direction(), collisionDistance(0.0f) {}
|
||||||
|
Ray::Ray( const Ray &ray ) : ICollideable(ICollideable::Ray), origin(ray.origin), direction(ray.direction), collisionDistance(0.0f) {}
|
||||||
|
Ray::Ray( const Float3 &o, const ::Oyster::Math::Float3 &d ) : ICollideable(ICollideable::Ray), origin(o), direction(d), collisionDistance(0.0f) {}
|
||||||
|
Ray::~Ray( ) { /*Nothing needs to be done here*/ }
|
||||||
|
|
||||||
|
Ray & Ray::operator = ( const Ray &ray )
|
||||||
|
{
|
||||||
|
this->origin = ray.origin;
|
||||||
|
this->direction = ray.direction;
|
||||||
|
this->collisionDistance = ray.collisionDistance;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ICollideable* Ray::clone( ) const
|
||||||
|
{ return new Ray( *this ); }
|
||||||
|
|
||||||
|
bool Ray::Intersects( const ICollideable *target ) const
|
||||||
|
{
|
||||||
|
switch( target->type )
|
||||||
|
{
|
||||||
|
case ICollideable::Point: return Utility::intersect( *this, *(Collision::Point*)target, this->collisionDistance );
|
||||||
|
case ICollideable::Ray: return Utility::intersect( *this, *(Collision::Ray*)target, this->collisionDistance, ((Collision::Ray*)target)->collisionDistance );
|
||||||
|
case ICollideable::Sphere: return Utility::intersect( *(Collision::Sphere*)target, *this, this->collisionDistance );
|
||||||
|
case ICollideable::Plane: return Utility::intersect( *(Collision::Plane*)target, *this, this->collisionDistance );
|
||||||
|
case ICollideable::Triangle: return false; // TODO
|
||||||
|
case ICollideable::BoxAxisAligned: return Utility::intersect( *(Collision::BoxAxisAligned*)target, *this, this->collisionDistance );
|
||||||
|
case ICollideable::Box: return Utility::intersect( *(Collision::Box*)target, *this, this->collisionDistance );
|
||||||
|
case ICollideable::Frustrum: return false; // TODO
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Ray::Contains( const ICollideable *target ) const
|
||||||
|
{
|
||||||
|
switch( target->type )
|
||||||
|
{
|
||||||
|
case ICollideable::Point: return Utility::intersect( *this, *(Collision::Point*)target, this->collisionDistance );
|
||||||
|
case ICollideable::Ray: Utility::contains( *this, *(Collision::Ray*)target );
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ICollideable::State Ray::Advanced( const ICollideable *target ) const
|
||||||
|
{ return ICollideable::Missed; } //Not supported returns 0
|
|
@ -0,0 +1,42 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/*
|
||||||
|
Ray::direction is assumed to be normalized!
|
||||||
|
- Dan
|
||||||
|
*/
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef OYSTER_COLLISION_RAY_H
|
||||||
|
#define OYSTER_COLLISION_RAY_H
|
||||||
|
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "ICollideable.h"
|
||||||
|
|
||||||
|
namespace Oyster { namespace Collision
|
||||||
|
{
|
||||||
|
class Ray : public ICollideable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct{ ::Oyster::Math::Float3 origin, direction; };
|
||||||
|
char byte[2*sizeof(::Oyster::Math::Float3)];
|
||||||
|
};
|
||||||
|
mutable float collisionDistance;
|
||||||
|
|
||||||
|
Ray( );
|
||||||
|
Ray( const Ray &ray );
|
||||||
|
Ray( const ::Oyster::Math::Float3 &origin, const ::Oyster::Math::Float3 &normalizedDirection );
|
||||||
|
~Ray( );
|
||||||
|
|
||||||
|
Ray & operator = ( const Ray &ray );
|
||||||
|
|
||||||
|
ICollideable* clone( ) const;
|
||||||
|
bool Intersects( const ICollideable *target ) const;
|
||||||
|
bool Contains( const ICollideable *target ) const;
|
||||||
|
ICollideable::State Advanced( const ICollideable *target ) const; //Not supported returns 0;
|
||||||
|
};
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,53 @@
|
||||||
|
#include "Sphere.h"
|
||||||
|
#include "Collision.h"
|
||||||
|
|
||||||
|
using namespace ::Oyster::Collision;
|
||||||
|
using namespace ::Oyster::Math;
|
||||||
|
|
||||||
|
Sphere::Sphere( ) : ICollideable(ICollideable::Sphere), center(), radius(0.0f) { }
|
||||||
|
Sphere::Sphere( const Sphere &sphere ) : ICollideable(ICollideable::Sphere), center(sphere.center), radius(sphere.radius) {}
|
||||||
|
Sphere::Sphere( const Float3 &_position, const Float &_radius ) : ICollideable(ICollideable::Sphere), center(_position), radius(_radius) {}
|
||||||
|
Sphere::~Sphere( ) { /*Nothing needs to be done here*/ }
|
||||||
|
|
||||||
|
Sphere & Sphere::operator = ( const Sphere &sphere )
|
||||||
|
{
|
||||||
|
this->center = sphere.center;
|
||||||
|
this->radius = sphere.radius;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ICollideable* Sphere::clone( ) const
|
||||||
|
{ return new Sphere( *this ); }
|
||||||
|
|
||||||
|
bool Sphere::Intersects( const ICollideable *target ) const
|
||||||
|
{
|
||||||
|
switch( target->type )
|
||||||
|
{
|
||||||
|
case ICollideable::Point: return Utility::intersect( *this, *(Collision::Point*)target );
|
||||||
|
case ICollideable::Ray: return Utility::intersect( *this, *(Collision::Ray*)target, ((Collision::Ray*)target)->collisionDistance );
|
||||||
|
case ICollideable::Sphere: Utility::intersect( *this, *(Collision::Sphere*)target );
|
||||||
|
case ICollideable::Plane: return Utility::intersect( *(Collision::Plane*)target, *this );
|
||||||
|
case ICollideable::Triangle: return false; // TODO
|
||||||
|
case ICollideable::BoxAxisAligned: return Utility::intersect( *(Collision::BoxAxisAligned*)target, *this );
|
||||||
|
case ICollideable::Box: return Utility::intersect( *(Collision::Box*)target, *this );
|
||||||
|
case ICollideable::Frustrum: return false; // TODO
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Sphere::Contains( const ICollideable *target ) const
|
||||||
|
{
|
||||||
|
switch( target->type )
|
||||||
|
{
|
||||||
|
case ICollideable::Point: return Utility::intersect( *this, *(Collision::Point*)target );
|
||||||
|
case ICollideable::Sphere: return Utility::contains( *this, *(Collision::Sphere*)target );
|
||||||
|
case ICollideable::Triangle: return false; // TODO
|
||||||
|
case ICollideable::BoxAxisAligned: return false; // TODO
|
||||||
|
case ICollideable::Box: return false; // TODO
|
||||||
|
case ICollideable::Frustrum: return false; // TODO
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ICollideable::State Sphere::Advanced( const ICollideable *target ) const
|
||||||
|
{ return ICollideable::Missed; } //Not supported returns 0
|
|
@ -0,0 +1,37 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef OYSTER_COLLISION_SPHERE_H
|
||||||
|
#define OYSTER_COLLISION_SPHERE_H
|
||||||
|
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "ICollideable.h"
|
||||||
|
|
||||||
|
namespace Oyster { namespace Collision
|
||||||
|
{
|
||||||
|
class Sphere : public ICollideable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct{ ::Oyster::Math::Float3 center; ::Oyster::Math::Float radius; };
|
||||||
|
char byte[sizeof(::Oyster::Math::Float3) + sizeof(::Oyster::Math::Float)];
|
||||||
|
};
|
||||||
|
|
||||||
|
Sphere( );
|
||||||
|
Sphere( const Sphere &point );
|
||||||
|
Sphere( const ::Oyster::Math::Float3 &position, const ::Oyster::Math::Float &radius );
|
||||||
|
~Sphere( );
|
||||||
|
|
||||||
|
Sphere & operator = ( const Sphere &sphere );
|
||||||
|
|
||||||
|
ICollideable* clone( ) const;
|
||||||
|
bool Intersects( const ICollideable *target ) const;
|
||||||
|
bool Contains( const ICollideable *target ) const;
|
||||||
|
ICollideable::State Advanced( const ICollideable *target ) const; //Not supported returns 0;
|
||||||
|
};
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,202 @@
|
||||||
|
#include "Buffer.h"
|
||||||
|
#include "Core.h"
|
||||||
|
using namespace Oyster;
|
||||||
|
|
||||||
|
Buffer::Buffer()
|
||||||
|
{
|
||||||
|
mBuffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::~Buffer()
|
||||||
|
{
|
||||||
|
SAFE_RELEASE(mBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Buffer::Apply(UINT32 misc) const
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
switch(mType)
|
||||||
|
{
|
||||||
|
case VERTEX_BUFFER:
|
||||||
|
{
|
||||||
|
UINT32 vertexSize = mElementSize;
|
||||||
|
UINT32 offset = 0;
|
||||||
|
Oyster::Core::DeviceContext->IASetVertexBuffers(misc, 1, &mBuffer, &vertexSize, &offset );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case INDEX_BUFFER:
|
||||||
|
{
|
||||||
|
Oyster::Core::DeviceContext->IASetIndexBuffer(mBuffer, DXGI_FORMAT_R32_UINT, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CONSTANT_BUFFER_VS:
|
||||||
|
{
|
||||||
|
Oyster::Core::DeviceContext->VSSetConstantBuffers(misc, 1, &mBuffer);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CONSTANT_BUFFER_GS:
|
||||||
|
{
|
||||||
|
Oyster::Core::DeviceContext->GSSetConstantBuffers(misc, 1, &mBuffer);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CONSTANT_BUFFER_PS:
|
||||||
|
{
|
||||||
|
Oyster::Core::DeviceContext->PSSetConstantBuffers(misc, 1, &mBuffer);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CONSTANT_BUFFER_CS:
|
||||||
|
{
|
||||||
|
Oyster::Core::DeviceContext->CSSetConstantBuffers(misc,1,&mBuffer);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
hr = E_FAIL;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Buffer::Init(const BUFFER_INIT_DESC& initDesc)
|
||||||
|
{
|
||||||
|
D3D11_BUFFER_DESC bufferDesc;
|
||||||
|
|
||||||
|
mType = initDesc.Type;
|
||||||
|
switch(mType)
|
||||||
|
{
|
||||||
|
case VERTEX_BUFFER:
|
||||||
|
{
|
||||||
|
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||||
|
|
||||||
|
if(initDesc.Usage == BUFFER_STREAM_OUT_TARGET)
|
||||||
|
bufferDesc.BindFlags |= D3D11_BIND_STREAM_OUTPUT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case INDEX_BUFFER:
|
||||||
|
{
|
||||||
|
bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STRUCTURED_BUFFER:
|
||||||
|
{
|
||||||
|
bufferDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CONSTANT_BUFFER_CS:
|
||||||
|
case CONSTANT_BUFFER_VS:
|
||||||
|
case CONSTANT_BUFFER_GS:
|
||||||
|
case CONSTANT_BUFFER_PS:
|
||||||
|
{
|
||||||
|
bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return E_FAIL;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
mUsage = initDesc.Usage;
|
||||||
|
mElementSize = initDesc.ElementSize;
|
||||||
|
mElementCount = initDesc.NumElements;
|
||||||
|
|
||||||
|
bufferDesc.CPUAccessFlags = 0;
|
||||||
|
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||||
|
|
||||||
|
if(mUsage == BUFFER_CPU_READ)
|
||||||
|
{
|
||||||
|
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||||
|
bufferDesc.CPUAccessFlags |= D3D11_CPU_ACCESS_READ;
|
||||||
|
}
|
||||||
|
else if(mUsage == BUFFER_CPU_WRITE)
|
||||||
|
{
|
||||||
|
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||||
|
bufferDesc.CPUAccessFlags |= D3D11_CPU_ACCESS_WRITE;
|
||||||
|
}
|
||||||
|
else if(mUsage == BUFFER_CPU_WRITE_DISCARD)
|
||||||
|
{
|
||||||
|
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||||
|
bufferDesc.CPUAccessFlags |= D3D11_CPU_ACCESS_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||||
|
bufferDesc.MiscFlags = 0;
|
||||||
|
bufferDesc.ByteWidth = initDesc.NumElements * initDesc.ElementSize;
|
||||||
|
bufferDesc.StructureByteStride=0;
|
||||||
|
if(mType== STRUCTURED_BUFFER)
|
||||||
|
{
|
||||||
|
bufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
|
||||||
|
bufferDesc.StructureByteStride=initDesc.ElementSize;
|
||||||
|
}
|
||||||
|
//set at least 16 bytes
|
||||||
|
if(bufferDesc.ByteWidth < 16)
|
||||||
|
bufferDesc.ByteWidth = 16;
|
||||||
|
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if(initDesc.InitData)
|
||||||
|
{
|
||||||
|
D3D11_SUBRESOURCE_DATA data;
|
||||||
|
data.pSysMem = initDesc.InitData;
|
||||||
|
data.SysMemPitch=0;
|
||||||
|
data.SysMemSlicePitch = 0;
|
||||||
|
hr = Oyster::Core::Device->CreateBuffer(&bufferDesc, &data, &mBuffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = Oyster::Core::Device->CreateBuffer(&bufferDesc, NULL, &mBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(FAILED(hr))
|
||||||
|
{
|
||||||
|
MessageBox(NULL, "Unable to create buffer.", "Slenda Error", MB_ICONERROR | MB_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Buffer::Map()
|
||||||
|
{
|
||||||
|
void* ret = NULL;
|
||||||
|
if(mUsage == BUFFER_CPU_WRITE || mUsage == BUFFER_CPU_READ || mUsage == BUFFER_CPU_WRITE_DISCARD)
|
||||||
|
{
|
||||||
|
D3D11_MAPPED_SUBRESOURCE MappedResource;
|
||||||
|
UINT32 mapType = 0;
|
||||||
|
|
||||||
|
if(mUsage == BUFFER_CPU_READ) mapType = D3D11_MAP_READ;
|
||||||
|
else if(mUsage == BUFFER_CPU_WRITE) mapType = D3D11_MAP_WRITE;
|
||||||
|
else if(mUsage == BUFFER_CPU_WRITE_DISCARD) mapType = D3D11_MAP_WRITE_DISCARD;
|
||||||
|
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if(FAILED(hr = Oyster::Core::DeviceContext->Map(
|
||||||
|
mBuffer,
|
||||||
|
0,
|
||||||
|
(D3D11_MAP)mapType,
|
||||||
|
0,
|
||||||
|
&MappedResource)))
|
||||||
|
{
|
||||||
|
ret = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = MappedResource.pData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::Unmap()
|
||||||
|
{
|
||||||
|
Oyster::Core::DeviceContext->Unmap( mBuffer, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::operator ID3D11Buffer *()
|
||||||
|
{
|
||||||
|
return this->mBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::operator const ID3D11Buffer *() const
|
||||||
|
{
|
||||||
|
return this->mBuffer;
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
#pragma once
|
||||||
|
#ifndef CoreBuffer
|
||||||
|
#define CoreBuffer
|
||||||
|
|
||||||
|
#include "Core.h"
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
class Buffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum BUFFER_TYPE
|
||||||
|
{
|
||||||
|
VERTEX_BUFFER,
|
||||||
|
INDEX_BUFFER,
|
||||||
|
CONSTANT_BUFFER_VS,
|
||||||
|
CONSTANT_BUFFER_GS,
|
||||||
|
CONSTANT_BUFFER_PS,
|
||||||
|
CONSTANT_BUFFER_CS,
|
||||||
|
STRUCTURED_BUFFER,
|
||||||
|
BUFFER_TYPE_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum BUFFER_USAGE
|
||||||
|
{
|
||||||
|
BUFFER_DEFAULT,
|
||||||
|
BUFFER_STREAM_OUT_TARGET,
|
||||||
|
BUFFER_CPU_WRITE,
|
||||||
|
BUFFER_CPU_WRITE_DISCARD,
|
||||||
|
BUFFER_CPU_READ,
|
||||||
|
BUFFER_USAGE_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BUFFER_INIT_DESC
|
||||||
|
{
|
||||||
|
BUFFER_TYPE Type;
|
||||||
|
UINT32 NumElements;
|
||||||
|
UINT32 ElementSize;
|
||||||
|
BUFFER_USAGE Usage;
|
||||||
|
void* InitData;
|
||||||
|
|
||||||
|
BUFFER_INIT_DESC()
|
||||||
|
{
|
||||||
|
InitData = NULL;
|
||||||
|
Usage = BUFFER_DEFAULT;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
protected:
|
||||||
|
ID3D11Buffer* mBuffer;
|
||||||
|
BUFFER_TYPE mType;
|
||||||
|
BUFFER_USAGE mUsage;
|
||||||
|
|
||||||
|
UINT32 mElementSize;
|
||||||
|
UINT32 mElementCount;
|
||||||
|
public:
|
||||||
|
Buffer();
|
||||||
|
virtual ~Buffer();
|
||||||
|
|
||||||
|
HRESULT Init(const BUFFER_INIT_DESC& initDesc);
|
||||||
|
|
||||||
|
void* Map();
|
||||||
|
void Unmap();
|
||||||
|
|
||||||
|
operator ID3D11Buffer*();
|
||||||
|
operator const ID3D11Buffer*() const;
|
||||||
|
|
||||||
|
HRESULT Apply(UINT32 misc = 0) const;
|
||||||
|
|
||||||
|
ID3D11Buffer* GetBufferPointer();
|
||||||
|
UINT32 GetVertexSize();
|
||||||
|
UINT32 GetElementCount();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,164 @@
|
||||||
|
#include "Core.h"
|
||||||
|
#include "..\Window\Window.h"
|
||||||
|
|
||||||
|
using namespace Oyster;
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
//GPU
|
||||||
|
ID3D11Device *Core::Device = NULL;
|
||||||
|
|
||||||
|
//API
|
||||||
|
ID3D11DeviceContext *Core::DeviceContext = NULL;
|
||||||
|
|
||||||
|
//SwapChain
|
||||||
|
IDXGISwapChain* Core::SwapChain = NULL;
|
||||||
|
|
||||||
|
std::stringstream Log;
|
||||||
|
|
||||||
|
inline std::stringstream* AccesLog(){return &Log;}
|
||||||
|
|
||||||
|
bool Core::Init(bool SingleThreaded, bool Reference,bool ForceDX11)
|
||||||
|
{
|
||||||
|
UINT createDeviceFlags = 0;
|
||||||
|
|
||||||
|
if( SingleThreaded )
|
||||||
|
createDeviceFlags = ::D3D11_CREATE_DEVICE_SINGLETHREADED;
|
||||||
|
|
||||||
|
::D3D_DRIVER_TYPE driverType = ::D3D_DRIVER_TYPE_HARDWARE;
|
||||||
|
|
||||||
|
if(Reference)
|
||||||
|
driverType = D3D_DRIVER_TYPE_REFERENCE;
|
||||||
|
|
||||||
|
/*#if defined(DEBUG) || defined(_DEBUG)
|
||||||
|
Log << "DirectX running in debug mode.\n";
|
||||||
|
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||||
|
#endif*/
|
||||||
|
|
||||||
|
|
||||||
|
D3D_FEATURE_LEVEL featureLevelsToTry[] =
|
||||||
|
{
|
||||||
|
D3D_FEATURE_LEVEL_11_0,
|
||||||
|
D3D_FEATURE_LEVEL_10_1,
|
||||||
|
D3D_FEATURE_LEVEL_10_0
|
||||||
|
};
|
||||||
|
D3D_FEATURE_LEVEL initiatedFeatureLevel;
|
||||||
|
|
||||||
|
if( FAILED( ::D3D11CreateDevice( NULL, // default adapter
|
||||||
|
driverType,
|
||||||
|
NULL, // no software device
|
||||||
|
createDeviceFlags,
|
||||||
|
featureLevelsToTry, 3, // default feature level array. DX11 support assumed
|
||||||
|
D3D11_SDK_VERSION,
|
||||||
|
&Device, // device
|
||||||
|
&initiatedFeatureLevel,
|
||||||
|
&DeviceContext ) ) ) // context
|
||||||
|
{ // if failed
|
||||||
|
if( DeviceContext ) { DeviceContext->Release(); DeviceContext = NULL; } // safe cleanup
|
||||||
|
if( Device ) { Device->Release(); Device = NULL; } // safe cleanup
|
||||||
|
}
|
||||||
|
|
||||||
|
if( driverType == ::D3D_DRIVER_TYPE_HARDWARE )
|
||||||
|
Log << "D3D_DRIVER_TYPE_HARDWARE support discovered.\n";
|
||||||
|
else
|
||||||
|
Log << "D3D_DRIVER_TYPE_REFERENCE support discovered.\n";
|
||||||
|
|
||||||
|
if( initiatedFeatureLevel == ::D3D_FEATURE_LEVEL_11_0 )
|
||||||
|
{
|
||||||
|
Log << "DirectX Featurelevel 11.0 supported.\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(ForceDX11)
|
||||||
|
return false;
|
||||||
|
if( initiatedFeatureLevel == ::D3D_FEATURE_LEVEL_10_1 )
|
||||||
|
{
|
||||||
|
Log << "DirectX Featurelevel 10.1 supported.\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( initiatedFeatureLevel == ::D3D_FEATURE_LEVEL_10_0 )
|
||||||
|
{
|
||||||
|
Log << "DirectX Featurelevel 10.0 supported.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Device)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Core::CreateSwapChain(HWND Window, int NrofBuffers,bool MSAA_Quality,bool Fullscreen)
|
||||||
|
{
|
||||||
|
//generate static Swapchain Desc
|
||||||
|
DXGI_SWAP_CHAIN_DESC desc;
|
||||||
|
desc.OutputWindow=Window;
|
||||||
|
desc.BufferCount=NrofBuffers;
|
||||||
|
desc.Windowed=!Fullscreen;
|
||||||
|
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_UNORDERED_ACCESS;
|
||||||
|
desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||||
|
desc.Flags=0;
|
||||||
|
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
||||||
|
desc.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED;
|
||||||
|
desc.BufferDesc.RefreshRate.Denominator=1;
|
||||||
|
desc.BufferDesc.RefreshRate.Numerator=60;
|
||||||
|
desc.BufferDesc.Height = Window::Size.bottom;
|
||||||
|
desc.BufferDesc.Width = Window::Size.left;
|
||||||
|
|
||||||
|
//Check and Set multiSampling
|
||||||
|
if(MSAA_Quality)
|
||||||
|
{
|
||||||
|
if(FAILED(Device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM,4,&desc.SampleDesc.Quality)))
|
||||||
|
{
|
||||||
|
Log<< "Failed to check multisample quality levels (MSAAQuality).\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
desc.SampleDesc.Count=4;
|
||||||
|
--desc.SampleDesc.Quality;
|
||||||
|
Log << "Supported multisample quality levels (MSAAQuality): " << desc.SampleDesc.Quality+1 << "x\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
desc.SampleDesc.Count=1;
|
||||||
|
desc.SampleDesc.Quality=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get Device Factory
|
||||||
|
::IDXGIDevice *dxgiDevice = NULL;
|
||||||
|
if( FAILED( Device->QueryInterface( __uuidof( IDXGIDevice ), (void**)&dxgiDevice ) ) )
|
||||||
|
{
|
||||||
|
Log << "Failed to Query for the GPU's dxgiDevice.\nFailed to create swapChain for the GPU.\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
::IDXGIAdapter *dxgiAdapter = NULL;
|
||||||
|
if( FAILED( dxgiDevice->GetParent( __uuidof( IDXGIAdapter ), (void**)&dxgiAdapter ) ) )
|
||||||
|
{
|
||||||
|
dxgiDevice->Release();
|
||||||
|
Log << "Failed to get GPU's parent dxgiAdapter.\nFailed to create swapChain for the GPU.\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
dxgiDevice->Release();
|
||||||
|
|
||||||
|
::IDXGIFactory *dxgiFactory = NULL;
|
||||||
|
if( FAILED( dxgiAdapter->GetParent( __uuidof( IDXGIFactory ), (void**)&dxgiFactory ) ) )
|
||||||
|
{
|
||||||
|
dxgiAdapter->Release();
|
||||||
|
Log << "Failed to get GPU's parent dxgiFactory.\nFailed to create swapChain for the GPU.\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
dxgiAdapter->Release();
|
||||||
|
|
||||||
|
//Create SwapChain
|
||||||
|
if( FAILED( dxgiFactory->CreateSwapChain( Device, &desc, &SwapChain ) ) )
|
||||||
|
{
|
||||||
|
dxgiFactory->Release();
|
||||||
|
Log << "Failed to create swapChain for the GPU.\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dxgiFactory->Release();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef Core_h
|
||||||
|
#define Core_h
|
||||||
|
|
||||||
|
|
||||||
|
#include "CoreIncludes.h"
|
||||||
|
#include <sstream>
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
class Core
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
static ID3D11Device* Device;
|
||||||
|
|
||||||
|
static ID3D11DeviceContext* DeviceContext;
|
||||||
|
|
||||||
|
static IDXGISwapChain* SwapChain;
|
||||||
|
|
||||||
|
static std::stringstream* AccesLog();
|
||||||
|
|
||||||
|
static bool Init(bool SingleThreaded,bool Reference,bool ForceDX11);
|
||||||
|
|
||||||
|
static bool CreateSwapChain(HWND Window, int NrofBuffers,bool MSAA_Quality,bool Fullscreen);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,40 @@
|
||||||
|
#pragma once
|
||||||
|
#ifndef CORE_INCLUDE
|
||||||
|
#define CORE_INCLUDE
|
||||||
|
|
||||||
|
#define NOMINMAX // Because I hate Microsoft now. ~Angry Dan.
|
||||||
|
// http://lolengine.net/blog/2011/3/4/fuck-you-microsoft-near-far-macros
|
||||||
|
#include <WinSock2.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <D3D11.h>
|
||||||
|
#include <D3DX11.h>
|
||||||
|
#include <D3DX10math.h>
|
||||||
|
#include <d3dx11effect.h>
|
||||||
|
#include <d3dCompiler.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#define SAFE_RELEASE(x) if( x ) { (x)->Release(); (x) = NULL; }
|
||||||
|
#define SAFE_DELETE(x) if( x ) { delete(x); (x) = NULL; }
|
||||||
|
#define SAFE_DELETE_ARRAY(x) if( x ) { delete[](x); (x) = NULL; }
|
||||||
|
#define PI (3.14159265358979323846f)
|
||||||
|
|
||||||
|
#pragma comment(lib, "d3d11.lib")
|
||||||
|
#pragma comment(lib, "d3dcompiler.lib")
|
||||||
|
#pragma comment (lib,"dxerr.lib")
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#pragma comment(lib, "d3dx11d.lib")
|
||||||
|
#pragma comment(lib, "Effects11D.lib")
|
||||||
|
#pragma comment(lib, "d3dx10d.lib")
|
||||||
|
#else
|
||||||
|
#pragma comment(lib, "d3dx11.lib")
|
||||||
|
#pragma comment(lib, "Effects11.lib")
|
||||||
|
#pragma comment(lib, "d3dx10.lib")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,539 @@
|
||||||
|
#include "Engine.h"
|
||||||
|
|
||||||
|
bool CreateDepthStencil(bool MSAA_Quality);
|
||||||
|
bool CreateRenderTarget();
|
||||||
|
void SetViewPort();
|
||||||
|
|
||||||
|
class oysterPrivates
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool instance,swapChained;
|
||||||
|
ID3D11DepthStencilView* depth;
|
||||||
|
ID3D11RenderTargetView *rtv;
|
||||||
|
ID3D11UnorderedAccessView *uav;
|
||||||
|
ID3D11ShaderResourceView* depthTexture;
|
||||||
|
DXGI_SAMPLE_DESC sampleDesc;
|
||||||
|
D3D11_VIEWPORT viewPort;
|
||||||
|
oysterPrivates():instance(false),swapChained(false),depth(NULL),rtv(NULL), depthTexture(NULL){};
|
||||||
|
class State
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int NrOfSamples;
|
||||||
|
int SampleSpread;
|
||||||
|
int NrOfPointlights;
|
||||||
|
}States;
|
||||||
|
|
||||||
|
}instance;
|
||||||
|
|
||||||
|
Oyster::Engine::Engine()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Oyster::Engine::~Engine()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//Init
|
||||||
|
bool Oyster::Engine::Init::IsInstanced()
|
||||||
|
{
|
||||||
|
return instance.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Oyster::Engine::Init::Instance(bool SingleThreaded,bool Reference,bool ForceDX11)
|
||||||
|
{
|
||||||
|
if(!instance.instance)
|
||||||
|
if(Oyster::Core::Init(SingleThreaded,Reference,ForceDX11))
|
||||||
|
instance.instance=true;
|
||||||
|
|
||||||
|
return instance.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Oyster::Engine::Init::HasSwapChain()
|
||||||
|
{
|
||||||
|
return instance.swapChained;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Oyster::Engine::Init::CreateSwapChain(HWND Window,int NrofBuffers,bool MSAA_Quality,bool Fullscreen)
|
||||||
|
{
|
||||||
|
if(Window==0)
|
||||||
|
{
|
||||||
|
if(Oyster::Window::Handle==0)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
Window = Oyster::Window::Handle;
|
||||||
|
}
|
||||||
|
if(!instance.swapChained)
|
||||||
|
{
|
||||||
|
if(Oyster::Core::CreateSwapChain(Window,NrofBuffers,MSAA_Quality,Fullscreen))
|
||||||
|
instance.swapChained=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance.swapChained;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Oyster::Engine::Init::InitializeWindow(const LPCSTR appName, const LPCSTR className,const HINSTANCE &hInstance, const int &nCmdShow, WNDPROC wProc, bool handleLoop )
|
||||||
|
{
|
||||||
|
return Oyster::Window::init(appName,className,hInstance,nCmdShow,wProc,handleLoop);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Oyster::Engine::Init::FullInit(const Setup& setup)
|
||||||
|
{
|
||||||
|
if(!Oyster::Engine::Init::Instance(setup.Common.SingleThreaded,setup.Common.Reference,setup.Common.ForceDX11))
|
||||||
|
return false;
|
||||||
|
if(setup.Window.InitWindow)
|
||||||
|
if(!Oyster::Engine::Init::InitializeWindow(setup.Window.appname,setup.Window.classname,setup.Window.hinstance,setup.Window.nCmdShow,setup.Window.wProc, true))
|
||||||
|
return false;
|
||||||
|
if(!Oyster::Engine::Init::CreateSwapChain(NULL,setup.Common.NrOfBuffers,setup.Common.MSAA_Quality,setup.Common.Fullscreen))
|
||||||
|
return false;
|
||||||
|
if(!Oyster::Shader::InitShaders())
|
||||||
|
return false;
|
||||||
|
if(setup.Common.GenerateDepthStencil)
|
||||||
|
if(!CreateDepthStencil(setup.Common.MSAA_Quality))
|
||||||
|
return false;
|
||||||
|
if(!CreateRenderTarget())
|
||||||
|
return false;
|
||||||
|
if(!Oyster::Render::Textbox::Init())
|
||||||
|
return false;
|
||||||
|
SetViewPort();
|
||||||
|
if(setup.Common.BindDefault)
|
||||||
|
Oyster::Engine::PrepareForRendering::BindRenderTargets(&instance.rtv,1,instance.depth);
|
||||||
|
|
||||||
|
instance.States.NrOfSamples = 14;
|
||||||
|
instance.States.SampleSpread = 4;
|
||||||
|
instance.States.NrOfPointlights = 1024;
|
||||||
|
|
||||||
|
Oyster::Resources::Buffers::Init();
|
||||||
|
Oyster::Resources::ShaderEffects::Init();
|
||||||
|
Oyster::Resources::PipeLineResourses::Init();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Oyster::Buffer* Oyster::Engine::Init::Buffers::CreateBuffer(const Oyster::Buffer::BUFFER_INIT_DESC desc)
|
||||||
|
{
|
||||||
|
Oyster::Buffer *buffy = new Oyster::Buffer();
|
||||||
|
buffy->Init(desc);
|
||||||
|
return buffy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//PrepareForRendering
|
||||||
|
void Oyster::Engine::PrepareForRendering::BindRenderTargets(ID3D11RenderTargetView** RenderTargets,int NrOfTargets,ID3D11DepthStencilView* depth)
|
||||||
|
{
|
||||||
|
Oyster::Core::DeviceContext->OMSetRenderTargets(NrOfTargets,RenderTargets,depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::PrepareForRendering::BindRenderTargets(ID3D11RenderTargetView** RenderTargets,int NrOfTargets)
|
||||||
|
{
|
||||||
|
Oyster::Core::DeviceContext->OMSetRenderTargets(NrOfTargets,RenderTargets,instance.depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::PrepareForRendering::BindBackBufferAsUAV()
|
||||||
|
{
|
||||||
|
Oyster::Core::DeviceContext->CSSetUnorderedAccessViews(0,1,&instance.uav,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::PrepareForRendering::BindUAV(ID3D11UnorderedAccessView** uav, int NrOfUavs)
|
||||||
|
{
|
||||||
|
Oyster::Core::DeviceContext->CSSetUnorderedAccessViews(0,NrOfUavs,uav,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::PrepareForRendering::ClearBackBuffer(Math::Float4 color)
|
||||||
|
{
|
||||||
|
Oyster::Core::DeviceContext->ClearRenderTargetView(instance.rtv,(float*)color);
|
||||||
|
Oyster::Core::DeviceContext->ClearDepthStencilView(instance.depth,1,1,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::PrepareForRendering::BindBackBuffer(ID3D11DepthStencilView* depth)
|
||||||
|
{
|
||||||
|
Oyster::Core::DeviceContext->OMSetRenderTargets(1,&instance.rtv,depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::PrepareForRendering::BindBackBuffer()
|
||||||
|
{
|
||||||
|
Oyster::Core::DeviceContext->OMSetRenderTargets(1,&instance.rtv,instance.depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::PrepareForRendering::Begin2DRender()
|
||||||
|
{
|
||||||
|
Oyster::Resources::Buffers::V2DSprites.Apply();
|
||||||
|
Oyster::Resources::Buffers::CBufferGs.Apply();
|
||||||
|
Shader::SetShaderEffect(Oyster::Resources::ShaderEffects::BasicSprite);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::PrepareForRendering::Begin2DTextRender()
|
||||||
|
{
|
||||||
|
Oyster::Render::Textbox::TextBuffer.Apply();
|
||||||
|
Oyster::Resources::Buffers::CBufferGs.Apply();
|
||||||
|
Oyster::Shader::SetShaderEffect(Oyster::Resources::ShaderEffects::Text2DEffect);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Render
|
||||||
|
void Oyster::Engine::Render::PresentScene()
|
||||||
|
{
|
||||||
|
Core::SwapChain->Present(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::Render::Geometry(const Oyster::Render::Model* models,int count,Oyster::Buffer* cBufferEveryObject, int slot)
|
||||||
|
{
|
||||||
|
if(cBufferEveryObject)
|
||||||
|
cBufferEveryObject->Apply(slot);
|
||||||
|
for(int i=0;i<count;++i)
|
||||||
|
{
|
||||||
|
if(models[i].Visible)
|
||||||
|
{
|
||||||
|
if(cBufferEveryObject)
|
||||||
|
{
|
||||||
|
void* data = cBufferEveryObject->Map();
|
||||||
|
memcpy(data,&(models[i].World->getTranspose()),64);
|
||||||
|
cBufferEveryObject->Unmap();
|
||||||
|
}
|
||||||
|
Oyster::Core::DeviceContext->PSSetShaderResources(0,models[i].info->Material.size(),&(models[i].info->Material[0]));
|
||||||
|
|
||||||
|
models[i].info->Vertices.Apply();
|
||||||
|
if(models[i].info->Indexed)
|
||||||
|
{
|
||||||
|
models[i].info->Indecies.Apply();
|
||||||
|
Oyster::Core::DeviceContext->DrawIndexed(models[i].info->VertexCount,0,0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Oyster::Core::DeviceContext->Draw(models[i].info->VertexCount,0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::Render::Text(std::string text, Oyster::Math::Float2 size, Oyster::Math::Float3 Pos)
|
||||||
|
{
|
||||||
|
Pos.x -= Oyster::Window::Size.left/2;
|
||||||
|
Pos.x += size.x;
|
||||||
|
|
||||||
|
Pos.y -= Oyster::Window::Size.bottom/2;
|
||||||
|
Pos.y += size.y;
|
||||||
|
|
||||||
|
Matrix m;
|
||||||
|
Math::identityMatrix(m);
|
||||||
|
float width = (1.0f/(Window::Size.left/2.0f));
|
||||||
|
float height = (1.0f/(Window::Size.bottom/2.0f));
|
||||||
|
m.m41=Pos.x * width;
|
||||||
|
m.m42=-Pos.y * height;
|
||||||
|
m.m43=Pos.z;
|
||||||
|
m.m11=width*size.x;
|
||||||
|
m.m22=height*size.y;
|
||||||
|
void* dest = Resources::Buffers::CBufferGs.Map();
|
||||||
|
memcpy(dest,&m.getTranspose(),64);
|
||||||
|
Resources::Buffers::CBufferGs.Unmap();
|
||||||
|
Oyster::Render::Textbox::Update(text, size.x);
|
||||||
|
Oyster::Engine::PrepareForRendering::Begin2DTextRender();
|
||||||
|
Oyster::Core::DeviceContext->PSSetShaderResources(0,1,&(Oyster::Render::Textbox::Texture));
|
||||||
|
//Should be able to be outside of the for loop. Keeping it here for now though.
|
||||||
|
Oyster::Core::DeviceContext->Draw(Oyster::Render::Textbox::NumLetters, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::Render::ScreenQuad(ID3D11ShaderResourceView* srv, float ZPos)
|
||||||
|
{
|
||||||
|
|
||||||
|
Oyster::Core::DeviceContext->PSSetShaderResources(0,1,&srv);
|
||||||
|
|
||||||
|
Matrix m;
|
||||||
|
Math::identityMatrix(m);
|
||||||
|
m.m43=ZPos;
|
||||||
|
|
||||||
|
void* dest = Resources::Buffers::CBufferGs.Map();
|
||||||
|
memcpy(dest,&m.getTranspose(),64);
|
||||||
|
Resources::Buffers::CBufferGs.Unmap();
|
||||||
|
|
||||||
|
Oyster::Core::DeviceContext->Draw(1,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::Render::Sprite(ID3D11ShaderResourceView* srv, Oyster::Math::Float2 size, Oyster::Math::Float3 Pos)
|
||||||
|
{
|
||||||
|
|
||||||
|
Oyster::Core::DeviceContext->PSSetShaderResources(0,1,&srv);
|
||||||
|
|
||||||
|
Pos.x -= Oyster::Window::Size.left/2;
|
||||||
|
Pos.x += size.x/2;
|
||||||
|
|
||||||
|
Pos.y -= Oyster::Window::Size.bottom/2;
|
||||||
|
Pos.y += size.y/2;
|
||||||
|
|
||||||
|
Matrix m;
|
||||||
|
Math::identityMatrix(m);
|
||||||
|
float width = (1.0f/(Window::Size.left/2.0f));
|
||||||
|
float height = (1.0f/(Window::Size.bottom/2.0f));
|
||||||
|
m.m41=Pos.x * width;
|
||||||
|
m.m42=-Pos.y * height;
|
||||||
|
m.m43=Pos.z;
|
||||||
|
m.m11=width*size.x/2;
|
||||||
|
m.m22=height*size.y/2;
|
||||||
|
|
||||||
|
void* dest = Resources::Buffers::CBufferGs.Map();
|
||||||
|
memcpy(dest,&m.getTranspose(),64);
|
||||||
|
Resources::Buffers::CBufferGs.Unmap();
|
||||||
|
|
||||||
|
Oyster::Core::DeviceContext->Draw(1,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Misc
|
||||||
|
bool CreateDepthStencil(bool MSAA_Quality)
|
||||||
|
{
|
||||||
|
|
||||||
|
D3D11_TEXTURE2D_DESC desc;
|
||||||
|
desc.MipLevels=1;
|
||||||
|
desc.ArraySize=1;
|
||||||
|
desc.Format = DXGI_FORMAT_D32_FLOAT;
|
||||||
|
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||||
|
desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
|
||||||
|
desc.CPUAccessFlags=0;
|
||||||
|
desc.MiscFlags=0;
|
||||||
|
desc.Height = Oyster::Window::Size.bottom;
|
||||||
|
desc.Width = Oyster::Window::Size.left;
|
||||||
|
|
||||||
|
|
||||||
|
//Check and Set multiSampling
|
||||||
|
if(MSAA_Quality)
|
||||||
|
{
|
||||||
|
if(FAILED(Oyster::Core::Device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM,4,&desc.SampleDesc.Quality)))
|
||||||
|
{
|
||||||
|
//Log<< "Failed to check multisample quality levels (MSAAQuality).\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
desc.SampleDesc.Count=4;
|
||||||
|
--desc.SampleDesc.Quality;
|
||||||
|
//Log << "Supported multisample quality levels (MSAAQuality): " << desc.SampleDesc.Quality+1 << "x\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
desc.SampleDesc.Count=1;
|
||||||
|
desc.SampleDesc.Quality=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ID3D11Texture2D* depthstencil;
|
||||||
|
|
||||||
|
if(FAILED(Oyster::Core::Device->CreateTexture2D(&desc,0,&depthstencil)))
|
||||||
|
return false;
|
||||||
|
if(FAILED(Oyster::Core::Device->CreateDepthStencilView(depthstencil,0,&instance.depth)))
|
||||||
|
{
|
||||||
|
depthstencil->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
depthstencil->Release();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreateRenderTarget()
|
||||||
|
{
|
||||||
|
D3D11_UNORDERED_ACCESS_VIEW_DESC descView;
|
||||||
|
ZeroMemory( &descView, sizeof(descView) );
|
||||||
|
descView.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
|
||||||
|
descView.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
descView.Texture2D.MipSlice=0;
|
||||||
|
|
||||||
|
ID3D11Texture2D* backBuffer;
|
||||||
|
if(FAILED(Oyster::Core::SwapChain->GetBuffer(0,__uuidof(ID3D11Texture2D),reinterpret_cast<void**>(&backBuffer))))
|
||||||
|
return false;
|
||||||
|
if(FAILED(Oyster::Core::Device->CreateRenderTargetView(backBuffer,0,&instance.rtv)))
|
||||||
|
{
|
||||||
|
backBuffer->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(FAILED(Oyster::Core::Device->CreateUnorderedAccessView(backBuffer,0,&instance.uav)))
|
||||||
|
{
|
||||||
|
backBuffer->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
backBuffer->Release();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetViewPort()
|
||||||
|
{
|
||||||
|
instance.viewPort.TopLeftX = 0.0f;
|
||||||
|
instance.viewPort.TopLeftY = 0.0f;
|
||||||
|
instance.viewPort.Width = (float)Oyster::Window::Size.left;
|
||||||
|
instance.viewPort.Height = (float)Oyster::Window::Size.bottom;
|
||||||
|
instance.viewPort.MinDepth = 0.0f;
|
||||||
|
instance.viewPort.MaxDepth = 1.0f;
|
||||||
|
|
||||||
|
Oyster::Core::DeviceContext->RSSetViewports(1,&instance.viewPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blur(int target)
|
||||||
|
{
|
||||||
|
//TODO: proper size calculation
|
||||||
|
|
||||||
|
//bind input
|
||||||
|
Oyster::Core::DeviceContext->CSSetShaderResources(0,1,&Oyster::Resources::PipeLineResourses::LightOut[target]);
|
||||||
|
Oyster::Engine::PrepareForRendering::BindUAV(&Oyster::Resources::PipeLineResourses::TempUav,1);
|
||||||
|
|
||||||
|
//dispatch blurr horizontal
|
||||||
|
Oyster::Shader::Set::SetCompute(Oyster::Shader::Get::GetCompute("BlurHorizontal"));
|
||||||
|
Oyster::Core::DeviceContext->Dispatch(7,Oyster::Window::Size.bottom,1);
|
||||||
|
|
||||||
|
//clean Pipeline
|
||||||
|
Oyster::Core::DeviceContext->CSSetShaderResources(0,16,&Oyster::Resources::PipeLineResourses::SrvNulls[0]);
|
||||||
|
Oyster::Core::DeviceContext->CSSetUnorderedAccessViews(0,8,&Oyster::Resources::PipeLineResourses::uavNULL[0],0);
|
||||||
|
|
||||||
|
//bind input
|
||||||
|
Oyster::Core::DeviceContext->CSSetShaderResources(0,1,&Oyster::Resources::PipeLineResourses::TempSrv);
|
||||||
|
Oyster::Engine::PrepareForRendering::BindUAV(&Oyster::Resources::PipeLineResourses::LightTarget[target],1);
|
||||||
|
|
||||||
|
//dispatch blurr vertical
|
||||||
|
Oyster::Shader::Set::SetCompute(Oyster::Shader::Get::GetCompute("BlurVertical"));
|
||||||
|
Oyster::Core::DeviceContext->Dispatch(Oyster::Window::Size.left,5,1);
|
||||||
|
|
||||||
|
//clean Pipeline
|
||||||
|
Oyster::Core::DeviceContext->CSSetShaderResources(0,16,&Oyster::Resources::PipeLineResourses::SrvNulls[0]);
|
||||||
|
Oyster::Core::DeviceContext->CSSetUnorderedAccessViews(0,8,&Oyster::Resources::PipeLineResourses::uavNULL[0],0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Pipeline Render
|
||||||
|
void Oyster::Engine::Pipeline::Deffered_Lightning::NewFrame(const Float4& col, const Matrix& View, const Matrix& Projection)
|
||||||
|
{
|
||||||
|
//diffuse
|
||||||
|
Oyster::Core::DeviceContext->ClearRenderTargetView( Oyster::Resources::PipeLineResourses::GeometryTarget[0], col);
|
||||||
|
|
||||||
|
//Specular
|
||||||
|
Oyster::Core::DeviceContext->ClearRenderTargetView( Oyster::Resources::PipeLineResourses::GeometryTarget[1], col);
|
||||||
|
|
||||||
|
//Glow
|
||||||
|
Oyster::Core::DeviceContext->ClearRenderTargetView( Oyster::Resources::PipeLineResourses::GeometryTarget[2], col);
|
||||||
|
|
||||||
|
//Pos
|
||||||
|
Oyster::Core::DeviceContext->ClearRenderTargetView( Oyster::Resources::PipeLineResourses::GeometryTarget[3], col);
|
||||||
|
|
||||||
|
//Normal
|
||||||
|
Oyster::Core::DeviceContext->ClearRenderTargetView( Oyster::Resources::PipeLineResourses::GeometryTarget[4], col);
|
||||||
|
|
||||||
|
Oyster::Engine::PrepareForRendering::ClearBackBuffer(col);
|
||||||
|
|
||||||
|
//Upload Camera to Resources
|
||||||
|
|
||||||
|
Matrix P = Oyster::Math::Float4x4(Projection);
|
||||||
|
Matrix V = Oyster::Math::Float4x4(View);
|
||||||
|
Matrix VP = V*P;
|
||||||
|
|
||||||
|
Oyster::Resources::PipeLineResourses::LightData.projectionMatrix = P.getTranspose();
|
||||||
|
Oyster::Resources::PipeLineResourses::LightData.viewMatrix = V;
|
||||||
|
|
||||||
|
Oyster::Collision::Frustrum( VP ).split(Oyster::Resources::PipeLineResourses::SubFrustrums, Oyster::Resources::PipeLineResourses::FrustrumDimensions.x, Oyster::Resources::PipeLineResourses::FrustrumDimensions.y, Oyster::Resources::PipeLineResourses::FrustrumDimensions.z );
|
||||||
|
|
||||||
|
void* dest = Oyster::Resources::ShaderEffects::ModelEffect.CBuffers.Vertex[0]->Map();
|
||||||
|
memcpy(dest,&VP.getTranspose(),64);
|
||||||
|
Oyster::Resources::ShaderEffects::ModelEffect.CBuffers.Vertex[0]->Unmap();
|
||||||
|
|
||||||
|
dest= Oyster::Resources::ShaderEffects::ModelEffect.CBuffers.Vertex[1]->Map();
|
||||||
|
memcpy(dest,&V.getTranspose(),64);
|
||||||
|
Oyster::Resources::ShaderEffects::ModelEffect.CBuffers.Vertex[1]->Unmap();
|
||||||
|
|
||||||
|
dest = Oyster::Resources::PipeLineResourses::Resources[0]->Map();
|
||||||
|
unsigned int bytes=0;
|
||||||
|
for(int i=0;i<Oyster::Resources::PipeLineResourses::FrustrumSize;++i)
|
||||||
|
{
|
||||||
|
Oyster::Resources::PipeLineResourses::SubFrustrums[i].writeToByte( (unsigned char*)dest,bytes);
|
||||||
|
}
|
||||||
|
Oyster::Resources::PipeLineResourses::Resources[0]->Unmap();
|
||||||
|
|
||||||
|
dest = Oyster::Resources::Buffers::CBufferPipelineCs.Map();
|
||||||
|
memcpy(dest, &Oyster::Resources::PipeLineResourses::LightData, sizeof( Oyster::Resources::BufferDefinitions::LightStructureBuffer ) );
|
||||||
|
Oyster::Resources::Buffers::CBufferPipelineCs.Unmap();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::Pipeline::Deffered_Lightning::BeginRenderGeometry()
|
||||||
|
{
|
||||||
|
Oyster::Engine::PrepareForRendering::BindRenderTargets( Oyster::Resources::PipeLineResourses::GeometryTarget, 5 );
|
||||||
|
Oyster::Shader::SetShaderEffect( Oyster::Resources::ShaderEffects::ModelEffect );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::Pipeline::Deffered_Lightning::RenderGeometry(const Oyster::Render::Model* models,int count)
|
||||||
|
{
|
||||||
|
//TODO: Add sorting to minimiza state changes
|
||||||
|
Render::Geometry( models, count, &Oyster::Resources::Buffers::CbufferVS, 2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::Pipeline::Deffered_Lightning::EndRenderGeometry()
|
||||||
|
{
|
||||||
|
//TODO: Actualy Render data from previous pass
|
||||||
|
Oyster::Engine::PrepareForRendering::BindRenderTargets( Oyster::Resources::PipeLineResourses::RtvNulls, 8, NULL );
|
||||||
|
Oyster::Core::DeviceContext->PSSetShaderResources(0, 16, Oyster::Resources::PipeLineResourses::SrvNulls);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::Pipeline::Deffered_Lightning::InputPointLights(Oyster::Resources::BufferDefinitions::PointLightDescription *p, int nr)
|
||||||
|
{
|
||||||
|
void* dest = Oyster::Resources::PipeLineResourses::Resources[1]->Map();
|
||||||
|
memcpy(dest, p, sizeof(Oyster::Resources::BufferDefinitions::PointLightDescription) * nr );
|
||||||
|
Oyster::Resources::PipeLineResourses::Resources[1]->Unmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::Pipeline::Deffered_Lightning::RenderLightning()
|
||||||
|
{
|
||||||
|
Oyster::Engine::PrepareForRendering::BindUAV( Oyster::Resources::PipeLineResourses::LightTarget, 4 );
|
||||||
|
Oyster::Core::DeviceContext->CSSetShaderResources(0,5, Oyster::Resources::PipeLineResourses::GeometryOut);
|
||||||
|
Oyster::Resources::Buffers::CBufferPipelineCs.Apply();
|
||||||
|
Oyster::Core::DeviceContext->CSSetShaderResources( 6, 4, Oyster::Resources::PipeLineResourses::ComputeResources );
|
||||||
|
Oyster::Shader::Set::SetCompute( Oyster::Shader::Get::GetCompute("Pass0") );
|
||||||
|
|
||||||
|
Oyster::Core::DeviceContext->Dispatch( 49, 36, 1 );
|
||||||
|
|
||||||
|
//clean Pipeline
|
||||||
|
Oyster::Core::DeviceContext->CSSetShaderResources( 0, 16, Oyster::Resources::PipeLineResourses::SrvNulls );
|
||||||
|
Oyster::Core::DeviceContext->CSSetUnorderedAccessViews( 0, 8, Oyster::Resources::PipeLineResourses::uavNULL, 0 );
|
||||||
|
|
||||||
|
//Blurr
|
||||||
|
//Blur( 2 );
|
||||||
|
//Blur( 3 );
|
||||||
|
|
||||||
|
//clean Pipeline
|
||||||
|
Oyster::Core::DeviceContext->CSSetShaderResources( 0, 16, Oyster::Resources::PipeLineResourses::SrvNulls );
|
||||||
|
Oyster::Core::DeviceContext->CSSetUnorderedAccessViews( 0, 8, Oyster::Resources::PipeLineResourses::uavNULL, 0 );
|
||||||
|
|
||||||
|
//prepare and render final pass
|
||||||
|
Oyster::Engine::PrepareForRendering::BindBackBufferAsUAV();
|
||||||
|
Oyster::Shader::Set::SetCompute( Oyster::Shader::Get::GetCompute("Pass1") );
|
||||||
|
Oyster::Core::DeviceContext->CSSetShaderResources( 0, 4, Oyster::Resources::PipeLineResourses::LightOut );
|
||||||
|
|
||||||
|
Oyster::Core::DeviceContext->Dispatch( 49, 36, 1 );
|
||||||
|
|
||||||
|
//clean Pipeline
|
||||||
|
Oyster::Core::DeviceContext->CSSetShaderResources( 0, 16, Oyster::Resources::PipeLineResourses::SrvNulls );
|
||||||
|
Oyster::Core::DeviceContext->CSSetUnorderedAccessViews( 0, 8, Oyster::Resources::PipeLineResourses::uavNULL, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//States
|
||||||
|
int Oyster::Engine::States::GetNrOfSSAOSamples()
|
||||||
|
{
|
||||||
|
return instance.States.NrOfSamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::States::SetNrOfSSAOSamples(int nr)
|
||||||
|
{
|
||||||
|
instance.States.NrOfSamples = nr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Oyster::Engine::States::GetSSAOSampleSpread()
|
||||||
|
{
|
||||||
|
return instance.States.SampleSpread;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::States::SetSSAOSampleSpread(int spread)
|
||||||
|
{
|
||||||
|
instance.States.SampleSpread = spread;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Oyster::Engine::States::GetMaxPointlights()
|
||||||
|
{
|
||||||
|
return instance.States.NrOfPointlights;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Engine::States::SetMaxPointlights(int nr)
|
||||||
|
{
|
||||||
|
instance.States.NrOfPointlights = nr;
|
||||||
|
}
|
|
@ -0,0 +1,177 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef Engine_h
|
||||||
|
#define Engine_h
|
||||||
|
|
||||||
|
#define NOMINMAX // Because I hate Microsoft now. ~Angry Dan. http://lolengine.net/blog/2011/3/4/fuck-you-microsoft-near-far-macros
|
||||||
|
|
||||||
|
#include "EngineIncludes.h"
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
class Engine
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Engine();
|
||||||
|
~Engine();
|
||||||
|
|
||||||
|
public:
|
||||||
|
class Init
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Setup
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
bool InitWindow;
|
||||||
|
LPCSTR appname;
|
||||||
|
LPCSTR classname;
|
||||||
|
HINSTANCE hinstance;
|
||||||
|
int nCmdShow;
|
||||||
|
WNDPROC wProc;
|
||||||
|
bool ManageWindow;
|
||||||
|
}Window;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int NrOfBuffers;
|
||||||
|
bool MSAA_Quality;
|
||||||
|
bool Fullscreen;
|
||||||
|
bool SingleThreaded;
|
||||||
|
bool Reference;
|
||||||
|
bool ForceDX11;
|
||||||
|
bool GenerateDepthStencil;
|
||||||
|
bool BindDefault;
|
||||||
|
}Common;
|
||||||
|
//all but Window params have Default Values
|
||||||
|
Setup()
|
||||||
|
{
|
||||||
|
Common.NrOfBuffers=1;
|
||||||
|
Common.MSAA_Quality = false;
|
||||||
|
Common.Fullscreen = true;
|
||||||
|
Common.SingleThreaded = true;
|
||||||
|
Common.Reference = false;
|
||||||
|
Common.ForceDX11 = false;
|
||||||
|
Common.GenerateDepthStencil = true;
|
||||||
|
Common.BindDefault = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool IsInstanced();
|
||||||
|
|
||||||
|
//Creates Device and DeviceContext, if not Initialized
|
||||||
|
static bool Instance(bool SingleThreaded=true,bool Reference=false,bool ForceDX11=false);
|
||||||
|
static bool HasSwapChain();
|
||||||
|
|
||||||
|
//Creates Swapchain, if not Aready Created
|
||||||
|
static bool CreateSwapChain(HWND Window, int NrofBuffers=1,bool MSAA_Quality=false,bool Fullscreen=true);
|
||||||
|
|
||||||
|
//CreateWindow, if Not Already Created
|
||||||
|
static bool InitializeWindow(const LPCSTR appName, const LPCSTR className,const HINSTANCE &hInstance, const int &nCmdShow, WNDPROC wProc, bool HandleLoop = false );
|
||||||
|
|
||||||
|
//Performs a full initialization of a rendering pipeline, including a Window
|
||||||
|
static bool FullInit(const Setup& setup);
|
||||||
|
struct Buffers
|
||||||
|
{
|
||||||
|
static Buffer* CreateBuffer(const Buffer::BUFFER_INIT_DESC BufferDesc);
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
Init();
|
||||||
|
~Init();
|
||||||
|
};
|
||||||
|
|
||||||
|
class States
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//SSAO Quality
|
||||||
|
static void SetNrOfSSAOSamples(int);
|
||||||
|
static int GetNrOfSSAOSamples();
|
||||||
|
|
||||||
|
//SSAO Frequency
|
||||||
|
static void SetSSAOSampleSpread(int);
|
||||||
|
static int GetSSAOSampleSpread();
|
||||||
|
|
||||||
|
//PointLights
|
||||||
|
static void SetMaxPointlights(int);
|
||||||
|
static int GetMaxPointlights();
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
States();
|
||||||
|
~States();
|
||||||
|
};
|
||||||
|
|
||||||
|
class Render
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Render a number of models, setting the Per model data to the included cBuffer
|
||||||
|
/// specify NULL if no such data exists
|
||||||
|
static void Geometry(const Oyster::Render::Model* models,int count,Oyster::Buffer* cBufferEveryObject, int slot);
|
||||||
|
static void Text(std::string text, Oyster::Math::Float2 size, Oyster::Math::Float3 Pos);
|
||||||
|
//static void TextBox(const Oyster::Render::
|
||||||
|
|
||||||
|
//ensure that a compatible 2D shadereffect is applied
|
||||||
|
static void ScreenQuad(ID3D11ShaderResourceView* srv, float ZPos=1);
|
||||||
|
|
||||||
|
//ensure that a compatible 2D shadereffect is applied and that pos.z is between 0 and 1
|
||||||
|
static void Sprite(ID3D11ShaderResourceView* srv, Oyster::Math::Float2 size, Oyster::Math::Float3 Pos);
|
||||||
|
|
||||||
|
static void PresentScene();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Render();
|
||||||
|
~Render();
|
||||||
|
};
|
||||||
|
|
||||||
|
class PrepareForRendering
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//Binds several rendertargets and a depthstencil
|
||||||
|
static void BindRenderTargets(ID3D11RenderTargetView** RenderTargets,int NrOfTargets,ID3D11DepthStencilView* depth);
|
||||||
|
|
||||||
|
//Binds several Rendertargest and a default depthstencil
|
||||||
|
static void BindRenderTargets(ID3D11RenderTargetView** RenderTargets,int NrOfTargets);
|
||||||
|
|
||||||
|
//Binds the backbuffer and a depthstencil
|
||||||
|
static void BindBackBuffer(ID3D11DepthStencilView* depth);
|
||||||
|
|
||||||
|
//Binds the backbuffer and a default depthstencil
|
||||||
|
static void BindBackBuffer();
|
||||||
|
|
||||||
|
//Binds the backbuffer to the compute shader
|
||||||
|
static void BindBackBufferAsUAV();
|
||||||
|
|
||||||
|
//binds several UAV to the computeshader
|
||||||
|
static void BindUAV(ID3D11UnorderedAccessView** uav, int NrOfUavs);
|
||||||
|
|
||||||
|
//Clears the backbuffer and default depthstencil
|
||||||
|
static void ClearBackBuffer(Math::Float4 color);
|
||||||
|
|
||||||
|
static void Begin2DRender();
|
||||||
|
|
||||||
|
static void Begin2DTextRender();
|
||||||
|
};
|
||||||
|
|
||||||
|
class Pipeline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class Deffered_Lightning
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//Basic Setup
|
||||||
|
static void NewFrame(const Float4& Color, const Matrix& View, const Matrix& Projection);
|
||||||
|
|
||||||
|
//Geometry Pass
|
||||||
|
static void BeginRenderGeometry();
|
||||||
|
static void RenderGeometry(const Oyster::Render::Model* models,int count);
|
||||||
|
static void EndRenderGeometry();
|
||||||
|
|
||||||
|
//Lightning Pass
|
||||||
|
static void InputPointLights(Oyster::Resources::BufferDefinitions::PointLightDescription *p, int NrOfPointlights );
|
||||||
|
static void RenderLightning();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,38 @@
|
||||||
|
//Oyster
|
||||||
|
|
||||||
|
// Render
|
||||||
|
#include "Render\Model.h"
|
||||||
|
#include "Render\Camera.h"
|
||||||
|
#include "Render\TextBox.h"
|
||||||
|
|
||||||
|
// Core
|
||||||
|
#include "Core\Core.h"
|
||||||
|
#include "Core\Buffer.h"
|
||||||
|
|
||||||
|
// Shader
|
||||||
|
#include "Shader\Shader.h"
|
||||||
|
|
||||||
|
// Math
|
||||||
|
#include "Math\OysterMath.h"
|
||||||
|
|
||||||
|
// FileLoader
|
||||||
|
#include "FileLoader\ObjReader.h"
|
||||||
|
|
||||||
|
// Windows
|
||||||
|
#include "Window\Window.h"
|
||||||
|
|
||||||
|
// Input
|
||||||
|
#include "Input\InputController.h"
|
||||||
|
|
||||||
|
// Collision
|
||||||
|
#include "Collision\Collision.h"
|
||||||
|
|
||||||
|
// Game Definitions
|
||||||
|
#include "Game\OysterGame.h"
|
||||||
|
|
||||||
|
// Resources
|
||||||
|
#include "Resourses\ShaderEffects.h"
|
||||||
|
#include "Resourses\Buffers.h"
|
||||||
|
#include "Resourses\PipelineResources.h"
|
||||||
|
#include "Resourses\GraphicsDefinitions.h"
|
||||||
|
#include "Resourses\Manager.h"
|
|
@ -0,0 +1,268 @@
|
||||||
|
#include "ObjReader.h"
|
||||||
|
#include "Utilities.h"
|
||||||
|
#include "..\Core\Core.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Oyster::FileLoaders;
|
||||||
|
using namespace Oyster;
|
||||||
|
using namespace Oyster::Math;
|
||||||
|
|
||||||
|
ObjReader *ObjReader::LoadFile(std::string fileName, Oyster::Math::Float4x4 transform)
|
||||||
|
{
|
||||||
|
static std::map<std::string, ObjReader *> cache;
|
||||||
|
|
||||||
|
ObjReader *reader = NULL;
|
||||||
|
|
||||||
|
if (cache.count(fileName))
|
||||||
|
{
|
||||||
|
reader = cache[fileName];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader = new ObjReader();
|
||||||
|
reader->ParseFile(fileName, transform);
|
||||||
|
|
||||||
|
cache[fileName] = reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjReader::ObjReader(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ObjReader::~ObjReader(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjReader::ParseFile(std::string fileName, Float4x4 transform)
|
||||||
|
{
|
||||||
|
ifstream input;
|
||||||
|
input.open(fileName.c_str());
|
||||||
|
|
||||||
|
if(!input.is_open())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string path;
|
||||||
|
Utility::String::extractDirPath(path,fileName,'\\');
|
||||||
|
|
||||||
|
std::vector<Vertex> VertexList;
|
||||||
|
std::vector<Float3> vList;
|
||||||
|
std::vector<Float3> nList;
|
||||||
|
std::vector<Float2> uvList;
|
||||||
|
Vertex vertex1, vertex2, vertex3;
|
||||||
|
Float3 face[3];
|
||||||
|
Float3 position, normal;
|
||||||
|
Float2 uv;
|
||||||
|
string s;
|
||||||
|
|
||||||
|
while(!input.eof())
|
||||||
|
{
|
||||||
|
getline(input,s);
|
||||||
|
int offset = (int)s.find(' ');
|
||||||
|
|
||||||
|
if(offset!=-1)
|
||||||
|
{
|
||||||
|
string c = s.substr(0,offset);
|
||||||
|
|
||||||
|
if(c=="v")
|
||||||
|
{
|
||||||
|
position = readVertex(offset,s);
|
||||||
|
vList.push_back(position);
|
||||||
|
}
|
||||||
|
else if(c=="vt")
|
||||||
|
{
|
||||||
|
uv = readUV(offset,s);
|
||||||
|
uvList.push_back(uv);
|
||||||
|
}
|
||||||
|
else if(c=="vn")
|
||||||
|
{
|
||||||
|
normal = readNormal(offset,s);
|
||||||
|
nList.push_back(normal);
|
||||||
|
}
|
||||||
|
else if(c=="f")
|
||||||
|
{
|
||||||
|
readFace(offset, s, face);
|
||||||
|
|
||||||
|
vertex1.Position = vList[(int)face[0].x];
|
||||||
|
vertex1.UV = uvList[(int)face[0].y];
|
||||||
|
vertex1.Normal = nList[(int)face[0].z];
|
||||||
|
|
||||||
|
vertex2.Position = vList[(int)face[1].x];
|
||||||
|
vertex2.UV = uvList[(int)face[1].y];
|
||||||
|
vertex2.Normal = nList[(int)face[1].z];
|
||||||
|
|
||||||
|
vertex3.Position = vList[(int)face[2].x];
|
||||||
|
vertex3.UV = uvList[(int)face[2].y];
|
||||||
|
vertex3.Normal = nList[(int)face[2].z];
|
||||||
|
|
||||||
|
VertexList.push_back(vertex1);
|
||||||
|
VertexList.push_back(vertex3);
|
||||||
|
VertexList.push_back(vertex2);
|
||||||
|
}
|
||||||
|
else if(c=="mtllib")
|
||||||
|
{
|
||||||
|
this->materials = GetMaterials(path+s.substr(offset+1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input.close();
|
||||||
|
|
||||||
|
this->numVertices = VertexList.size();
|
||||||
|
this->vertices = new Vertex[this->numVertices];
|
||||||
|
|
||||||
|
for(size_t i=0;i<this->numVertices;++i)
|
||||||
|
{
|
||||||
|
vertices[i].Position=Math::transformVector(Math::Float4(VertexList[i].Position,1),transform);
|
||||||
|
vertices[i].Normal=Math::transformVector(Math::Float4(VertexList[i].Normal,0),transform);
|
||||||
|
vertices[i].UV = VertexList[i].UV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjReader::GetVertexData(Vertex **vertex,int &numVertex, std::map<std::string, ID3D11ShaderResourceView *> &Textures)
|
||||||
|
{
|
||||||
|
numVertex=(int)this->numVertices;
|
||||||
|
(*vertex)=this->vertices;
|
||||||
|
Textures = this->materials;
|
||||||
|
}
|
||||||
|
|
||||||
|
Float3 ObjReader::extract(std::string d)
|
||||||
|
{
|
||||||
|
Float3 data;
|
||||||
|
int offset=(int)d.find('/');
|
||||||
|
data.x=(float)atoi(d.substr(1,offset).c_str())-1;
|
||||||
|
|
||||||
|
int newOffset = (int)d.find('/',offset+1);
|
||||||
|
string d2=d.substr(offset+1,newOffset-offset-1);
|
||||||
|
data.y=(float)atoi(d2.c_str())-1;
|
||||||
|
offset=newOffset;
|
||||||
|
|
||||||
|
newOffset = (int)d.find('/',offset+1);
|
||||||
|
string d3=d.substr(offset+1,newOffset-offset-1);
|
||||||
|
data.z=(float)atoi(d3.c_str())-1;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Float3 ObjReader::readVertex(int offset,string s)
|
||||||
|
{
|
||||||
|
int newOffset = (int)s.find(' ',offset+1);
|
||||||
|
Float3 vertex;
|
||||||
|
string d = s.substr(offset,newOffset-offset);
|
||||||
|
vertex.x = (float)atof(d.c_str());
|
||||||
|
offset=newOffset;
|
||||||
|
|
||||||
|
newOffset = (int)s.find(' ',offset+1);
|
||||||
|
vertex.y = (float)atof(s.substr(offset,newOffset-offset).c_str());
|
||||||
|
offset=newOffset;
|
||||||
|
|
||||||
|
newOffset = (int)s.find(' ',offset+1);
|
||||||
|
vertex.z = (float)-atof(s.substr(offset,newOffset-offset).c_str());
|
||||||
|
|
||||||
|
return vertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
Float2 ObjReader::readUV(int offset,string s)
|
||||||
|
{
|
||||||
|
int newOffset = (int)s.find(' ',offset+1);
|
||||||
|
Float2 uv;
|
||||||
|
string d = s.substr(offset,newOffset-offset);
|
||||||
|
uv.x =(float)atof(d.c_str());
|
||||||
|
offset=newOffset;
|
||||||
|
|
||||||
|
newOffset = (int)s.find(' ',offset+1);
|
||||||
|
d = s.substr(offset,newOffset-offset);
|
||||||
|
uv.y =1- (float)atof(d.c_str());
|
||||||
|
offset=newOffset;
|
||||||
|
|
||||||
|
return uv;
|
||||||
|
}
|
||||||
|
|
||||||
|
Float3 ObjReader::readNormal(int offset,string s)
|
||||||
|
{
|
||||||
|
int newOffset = (int)s.find(' ',offset+1);
|
||||||
|
Float3 vertex;
|
||||||
|
string d = s.substr(offset,newOffset-offset);
|
||||||
|
vertex.x = (float)atof(d.c_str());
|
||||||
|
offset=newOffset;
|
||||||
|
|
||||||
|
newOffset = (int)s.find(' ',offset+1);
|
||||||
|
vertex.y = (float)atof(s.substr(offset,newOffset-offset).c_str());
|
||||||
|
offset=newOffset;
|
||||||
|
|
||||||
|
newOffset = (int)s.find(' ',offset+1);
|
||||||
|
vertex.z = (float)-atof(s.substr(offset,newOffset-offset).c_str());
|
||||||
|
|
||||||
|
return vertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjReader::readFace(int offset,string s, Oyster::Math::Float3 face[3])
|
||||||
|
{
|
||||||
|
int newOffset = (int)s.find(' ',offset+1);
|
||||||
|
string point1 = s.substr(offset,newOffset-offset);
|
||||||
|
|
||||||
|
offset = newOffset;
|
||||||
|
newOffset = (int)s.find(' ',offset+1);
|
||||||
|
string point2 = s.substr(offset,newOffset-offset);
|
||||||
|
|
||||||
|
offset = newOffset;
|
||||||
|
newOffset = (int)s.find(' ',offset+1);
|
||||||
|
string point3 = s.substr(offset,newOffset-offset);
|
||||||
|
|
||||||
|
face[0] = extract(point1);
|
||||||
|
face[1] = extract(point2);
|
||||||
|
face[2] = extract(point3);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, ID3D11ShaderResourceView *> ObjReader::GetMaterials(std::string fileName)
|
||||||
|
{
|
||||||
|
ifstream input;
|
||||||
|
input.open(fileName.c_str());
|
||||||
|
|
||||||
|
std::map<std::string, ID3D11ShaderResourceView *> materials;
|
||||||
|
ID3D11ShaderResourceView *srv;
|
||||||
|
string texture;
|
||||||
|
string s;
|
||||||
|
string path;
|
||||||
|
Utility::String::extractDirPath(path,fileName,'\\');
|
||||||
|
if(!input.is_open())
|
||||||
|
return materials;
|
||||||
|
|
||||||
|
while(!input.eof())
|
||||||
|
{
|
||||||
|
getline(input,s);
|
||||||
|
int offset = (int)s.find(' ');
|
||||||
|
if(offset!=-1)
|
||||||
|
{
|
||||||
|
string c = s.substr(0,offset);
|
||||||
|
if(c=="map_Kd")
|
||||||
|
{
|
||||||
|
texture = path+s.substr(offset+1);
|
||||||
|
D3DX11CreateShaderResourceViewFromFile(Oyster::Core::Device,texture.c_str(), NULL, NULL, &srv, NULL);
|
||||||
|
materials["Diffuse"] = srv;
|
||||||
|
}
|
||||||
|
if(c=="map_G")
|
||||||
|
{
|
||||||
|
texture = path+s.substr(offset+1);
|
||||||
|
D3DX11CreateShaderResourceViewFromFile(Oyster::Core::Device,texture.c_str(), NULL, NULL, &srv, NULL);
|
||||||
|
materials["Glow"] = srv;
|
||||||
|
}
|
||||||
|
if(c=="map_Ks")
|
||||||
|
{
|
||||||
|
texture = path+s.substr(offset+1);
|
||||||
|
D3DX11CreateShaderResourceViewFromFile(Oyster::Core::Device,texture.c_str(), NULL, NULL, &srv, NULL);
|
||||||
|
materials["Specular"] = srv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input.close();
|
||||||
|
|
||||||
|
return materials;
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
#pragma once
|
||||||
|
#include "..\Core\CoreIncludes.h"
|
||||||
|
#include "..\Math\OysterMath.h"
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace FileLoaders
|
||||||
|
{
|
||||||
|
class ObjReader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Vertex
|
||||||
|
{
|
||||||
|
Oyster::Math::Float3 Position;
|
||||||
|
Oyster::Math::Float3 Normal;
|
||||||
|
Oyster::Math::Float2 UV;
|
||||||
|
};
|
||||||
|
|
||||||
|
static ObjReader *LoadFile(std::string fileName, Oyster::Math::Float4x4 transform = Oyster::Math::Float4x4::identity);
|
||||||
|
|
||||||
|
ObjReader(void);
|
||||||
|
~ObjReader(void);
|
||||||
|
|
||||||
|
void GetVertexData(Vertex **vertex,int &numVertex, std::map<std::string, ID3D11ShaderResourceView *> &textures);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vertex *vertices;
|
||||||
|
size_t numVertices;
|
||||||
|
std::map<std::string, ID3D11ShaderResourceView *> materials;
|
||||||
|
|
||||||
|
void ParseFile(std::string fileName, Oyster::Math::Float4x4 transform = Oyster::Math::Float4x4::identity);
|
||||||
|
|
||||||
|
Oyster::Math::Float3 extract(std::string d);
|
||||||
|
Oyster::Math::Float3 readVertex(int offset,std::string s);
|
||||||
|
Oyster::Math::Float2 readUV(int offset,std::string s);
|
||||||
|
Oyster::Math::Float3 readNormal(int offset,std::string s);
|
||||||
|
void readFace(int offset,std::string s, Oyster::Math::Float3 face[3]);
|
||||||
|
|
||||||
|
std::map<std::string, ID3D11ShaderResourceView *> GetMaterials(std::string fileName);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,356 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef OYSTER_COLLISIONHANDLER_H
|
||||||
|
#define OYSTER_COLLISIONHANDLER_H
|
||||||
|
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "Sphere.h"
|
||||||
|
|
||||||
|
using namespace Oyster::Math;
|
||||||
|
using namespace Oyster::Collision;
|
||||||
|
|
||||||
|
namespace Oyster { namespace Game
|
||||||
|
{
|
||||||
|
// HEAD /////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
class CollisionHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class Reference
|
||||||
|
{
|
||||||
|
friend class CollisionHandler;
|
||||||
|
public:
|
||||||
|
static const Reference invalid;
|
||||||
|
|
||||||
|
Reference( const Reference &ref );
|
||||||
|
~Reference( );
|
||||||
|
|
||||||
|
bool operator == ( const Reference &ref ) const;
|
||||||
|
bool operator != ( const Reference &ref ) const;
|
||||||
|
|
||||||
|
Float getBoundaryReach( ) const;
|
||||||
|
const Float3 & getPosition( ) const;
|
||||||
|
// const Float & getScaling( ) const;
|
||||||
|
const unsigned int & getChannel( ) const;
|
||||||
|
CollisionHandler * getHandler( ) const;
|
||||||
|
|
||||||
|
void setBoundaryReach( const Float &radius );
|
||||||
|
void setPosition( const Float3 &position );
|
||||||
|
// void setScale( const Float &scale );
|
||||||
|
|
||||||
|
void moveToLimbo( );
|
||||||
|
void leaveLimbo( );
|
||||||
|
|
||||||
|
bool isActive( ) const;
|
||||||
|
bool isInLimbo( ) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CollisionHandler *handler;
|
||||||
|
unsigned int ref;
|
||||||
|
|
||||||
|
Reference( CollisionHandler *handler = NULL, unsigned int ref = 0 );
|
||||||
|
};
|
||||||
|
static const typename Reference outOfSlots;
|
||||||
|
|
||||||
|
class VisitingInstance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~VisitingInstance( ) {};
|
||||||
|
virtual void action( Entity *hitEntity ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*VisitingAction)( Entity *visitor, Entity *hitEntity );
|
||||||
|
|
||||||
|
CollisionHandler( );
|
||||||
|
virtual ~CollisionHandler( );
|
||||||
|
|
||||||
|
void emptyAndReInit( unsigned int maxNumEntities, unsigned int numChannels );
|
||||||
|
void update( );
|
||||||
|
|
||||||
|
Reference addEntity( unsigned int channel, Entity *entity, const ::Oyster::Collision::Sphere &collisionBubble, const Float &scale = 1.0f );
|
||||||
|
void visit( unsigned int *channels, unsigned int numChannels, const ::Oyster::Collision::ICollideable *sampler, VisitingInstance *visitor );
|
||||||
|
void visit( unsigned int *channels, unsigned int numChannels, const ::Oyster::Collision::ICollideable *sampler, Entity *visitor, VisitingAction action );
|
||||||
|
bool collidesWithSomething( unsigned int *channels, unsigned int numChannels, const ::Oyster::Collision::ICollideable *sampler );
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum State { Updated, Changed, Limbo, Vacant };
|
||||||
|
struct Data { Entity *entity; unsigned int channel, numHooks; Float scale; State state; } *data;
|
||||||
|
::Oyster::Collision::Sphere *presence;
|
||||||
|
unsigned int maxNumEntities, numEntities;
|
||||||
|
|
||||||
|
// TODO: Optimize by implementing a BSP oct tree here below (A)
|
||||||
|
|
||||||
|
struct Channel { Channel(); unsigned int *content, num; } *channel;
|
||||||
|
unsigned int numChannels;
|
||||||
|
|
||||||
|
bool simpleCollisionConfirmation( const typename Entity &entity, const ::Oyster::Collision::ICollideable *sampler );
|
||||||
|
};
|
||||||
|
|
||||||
|
// BODY /////////////////////////////////////////////////////////////
|
||||||
|
template<typename Entity>
|
||||||
|
const typename CollisionHandler<Entity>::Reference CollisionHandler<Entity>::outOfSlots = CollisionHandler<Entity>::Reference();
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
CollisionHandler<Entity>::CollisionHandler( ) : data(NULL), presence(NULL), maxNumEntities(0), numEntities(0), channel(NULL), numChannels(0) {}
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
CollisionHandler<Entity>::~CollisionHandler( )
|
||||||
|
{
|
||||||
|
if( this->data ) delete [] this->data;
|
||||||
|
if( this->presence ) delete [] this->presence;
|
||||||
|
|
||||||
|
// TODO: Optimize by implementing a BSP oct tree here below (B)
|
||||||
|
if( this->channel )
|
||||||
|
{
|
||||||
|
for( unsigned int i = 0; i < this->numChannels; ++i ) if( this->channel[i].content )
|
||||||
|
delete [] this->channel[i].content;
|
||||||
|
delete [] this->channel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
void CollisionHandler<Entity>::emptyAndReInit( unsigned int maxNumEntities, unsigned int numChannels )
|
||||||
|
{
|
||||||
|
if( this->data ) delete [] this->data;
|
||||||
|
if( this->presence ) delete [] this->presence;
|
||||||
|
|
||||||
|
this->maxNumEntities = maxNumEntities;
|
||||||
|
this->numEntities = 0;
|
||||||
|
if( maxNumEntities > 0 )
|
||||||
|
{
|
||||||
|
this->data = new CollisionHandler<Entity>::Data[maxNumEntities];
|
||||||
|
this->presence = new Sphere[maxNumEntities];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->data = NULL;
|
||||||
|
this->presence = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Optimize by implementing a BSP oct tree here below (C)
|
||||||
|
if( this->channel )
|
||||||
|
{
|
||||||
|
for( unsigned int i = 0; i < this->numChannels; ++i ) if( this->channel[i].content )
|
||||||
|
delete [] this->channel[i].content;
|
||||||
|
delete [] this->channel;
|
||||||
|
}
|
||||||
|
this->numChannels = numChannels;
|
||||||
|
this->channel = numChannels > 0 ? new CollisionHandler<Entity>::Channel[numChannels] : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
void CollisionHandler<Entity>::update( )
|
||||||
|
{
|
||||||
|
// TODO: Optimize by implementing a BSP oct tree here below (D)
|
||||||
|
for( unsigned int i = 0; i < this->numEntities; ++i ) if( this->data[i].state == CollisionHandler<Entity>::Changed )
|
||||||
|
this->data[i].state = CollisionHandler<Entity>::Updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
typename CollisionHandler<Entity>::Reference CollisionHandler<Entity>::addEntity( unsigned int channel, typename Entity *entity, const ::Oyster::Collision::Sphere &collisionBubble, const Float &scale )
|
||||||
|
{
|
||||||
|
if( this->numEntities < this->maxNumEntities )
|
||||||
|
{
|
||||||
|
this->data[this->numEntities].entity = entity;
|
||||||
|
this->data[this->numEntities].channel = channel;
|
||||||
|
this->data[this->numEntities].numHooks = 0;
|
||||||
|
this->data[this->numEntities].scale = scale;
|
||||||
|
this->data[this->numEntities].state = CollisionHandler<Entity>::Updated;
|
||||||
|
this->presence[this->numEntities] = collisionBubble;
|
||||||
|
|
||||||
|
// TODO: Optimize by implementing a BSP oct tree here below (E)
|
||||||
|
|
||||||
|
if( this->channel[channel].content == NULL )
|
||||||
|
{
|
||||||
|
this->channel[channel].content = new unsigned int[this->maxNumEntities];
|
||||||
|
this->channel[channel].num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->channel[channel].content[this->channel[channel].num] = this->numEntities;
|
||||||
|
++this->channel[channel].num;
|
||||||
|
|
||||||
|
//////
|
||||||
|
return CollisionHandler<Entity>::Reference( this, this->numEntities++ );
|
||||||
|
}
|
||||||
|
else return CollisionHandler<Entity>::outOfSlots;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
void CollisionHandler<Entity>::visit( unsigned int *_channel, unsigned int _numChannels, const ::Oyster::Collision::ICollideable *sampler, typename CollisionHandler<Entity>::VisitingInstance *visitor )
|
||||||
|
{
|
||||||
|
// TODO: Optimize by implementing a BSP oct tree here below (F1)
|
||||||
|
for( unsigned int ch = 0; ch < _numChannels; ++ch )
|
||||||
|
for( unsigned int i = 0; i < this->channel[_channel[ch]].num; ++i )
|
||||||
|
if( this->data[this->channel[ch].content[i]].state != CollisionHandler<Entity>::Limbo && this->data[this->channel[ch].content[i]].state != CollisionHandler<Entity>::Vacant )
|
||||||
|
if( sampler->Intersects( &this->presence[this->channel[ch].content[i]] ) )
|
||||||
|
visitor->action( this->data[this->channel[ch].content[i]].entity );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
void CollisionHandler<Entity>::visit( unsigned int *_channel, unsigned int _numChannels, const ::Oyster::Collision::ICollideable *sampler, typename Entity *visitor, typename CollisionHandler<Entity>::VisitingAction action )
|
||||||
|
{
|
||||||
|
// TODO: Optimize by implementing a BSP oct tree here below (F2)
|
||||||
|
for( unsigned int ch = 0; ch < _numChannels; ++ch )
|
||||||
|
for( unsigned int i = 0; i < this->channel[_channel[ch]].num; ++i )
|
||||||
|
if( this->data[this->channel[ch].content[i]].state != CollisionHandler<Entity>::Limbo && this->data[this->channel[ch].content[i]].state != CollisionHandler<Entity>::Vacant )
|
||||||
|
if( sampler->Intersects( &this->presence[this->channel[ch].content[i]] ) )
|
||||||
|
action( visitor, this->data[this->channel[ch].content[i]].entity );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
bool CollisionHandler<Entity>::collidesWithSomething( unsigned int *_channel, unsigned int _numChannels, const ::Oyster::Collision::ICollideable *sampler )
|
||||||
|
{
|
||||||
|
// TODO: Optimize by implementing a BSP oct tree here below (F3)
|
||||||
|
for( unsigned int ch = 0; ch < _numChannels; ++ch )
|
||||||
|
for( unsigned int i = 0; i < this->channel[_channel[ch]].num; ++i )
|
||||||
|
if( this->data[this->channel[ch].content[i]].state != CollisionHandler<Entity>::Limbo && this->data[this->channel[ch].content[i]].state != CollisionHandler<Entity>::Vacant )
|
||||||
|
if( sampler->Intersects( &this->presence[this->channel[ch].content[i]] ) )
|
||||||
|
if( this->simpleCollisionConfirmation(*this->data[this->channel[ch].content[i]].entity, sampler) )
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
bool CollisionHandler<Entity>::simpleCollisionConfirmation( const typename Entity &entity, const ::Oyster::Collision::ICollideable *sampler )
|
||||||
|
{ return true; }
|
||||||
|
|
||||||
|
// CollisionHandler::Channel ////////////////////////////////////
|
||||||
|
template<typename Entity>
|
||||||
|
CollisionHandler<Entity>::Channel::Channel( ) : content(NULL), num(0) {}
|
||||||
|
|
||||||
|
// CollisionHandler::Reference ////////////////////////////
|
||||||
|
|
||||||
|
template<typename Entity> const typename CollisionHandler<Entity>::Reference CollisionHandler<Entity>::Reference::invalid = CollisionHandler<Entity>::Reference();
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
CollisionHandler<Entity>::Reference::Reference( CollisionHandler *_handler, unsigned int _ref )
|
||||||
|
: handler(_handler), ref(_ref)
|
||||||
|
{ /* TODO : implement a slot allocation system */
|
||||||
|
if( this->handler )
|
||||||
|
{
|
||||||
|
++this->handler->data[this->ref].numHooks;
|
||||||
|
if( this->handler->data[this->ref].state == CollisionHandler<Entity>::Vacant )
|
||||||
|
this->handler->data[this->ref].state = CollisionHandler<Entity>::Limbo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
CollisionHandler<Entity>::Reference::Reference( const Reference &ref )
|
||||||
|
: handler(ref.handler), ref(ref.ref)
|
||||||
|
{ /* TODO : implement a slot allocation system */
|
||||||
|
if( this->handler )
|
||||||
|
{
|
||||||
|
++this->handler->data[this->ref].numHooks;
|
||||||
|
if( this->handler->data[this->ref].state == CollisionHandler<Entity>::Vacant )
|
||||||
|
this->handler->data[this->ref].state = CollisionHandler<Entity>::Limbo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
CollisionHandler<Entity>::Reference::~Reference( )
|
||||||
|
{ /* TODO : implement a slot allocation system */
|
||||||
|
if( this->handler )
|
||||||
|
{
|
||||||
|
if( this->handler->data[this->ref].numHooks > 0 )
|
||||||
|
if( --this->handler->data[this->ref].numHooks == 0 )
|
||||||
|
this->handler->data[this->ref].state = CollisionHandler<Entity>::Vacant;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
bool CollisionHandler<Entity>::Reference::operator == ( const typename CollisionHandler<Entity>::Reference &ref ) const
|
||||||
|
{
|
||||||
|
if( this->handler != ref.handler ) return false;
|
||||||
|
if( this->ref != ref.ref ) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
bool CollisionHandler<Entity>::Reference::operator != ( const typename CollisionHandler<Entity>::Reference &ref ) const
|
||||||
|
{
|
||||||
|
if( this->handler != ref.handler ) return true;
|
||||||
|
if( this->ref != ref.ref ) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
Float CollisionHandler<Entity>::Reference::getBoundaryReach( ) const
|
||||||
|
{ return this->handler->presence[this->ref].radius; }// / this->handler->data[this->ref].scale; }
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
const Float3 & CollisionHandler<Entity>::Reference::getPosition( ) const
|
||||||
|
{ return this->handler->presence[this->ref].center; }
|
||||||
|
|
||||||
|
// template<typename Entity>
|
||||||
|
// const Float & CollisionHandler<Entity>::Reference::getScaling( ) const
|
||||||
|
// { return this->handler->data[this->ref].scale; }
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
const unsigned int & CollisionHandler<Entity>::Reference::getChannel( ) const
|
||||||
|
{ return this->handler->data[this->ref].channel; }
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
CollisionHandler<Entity> * CollisionHandler<Entity>::Reference::getHandler( ) const
|
||||||
|
{ return this->handler; }
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
void CollisionHandler<Entity>::Reference::setBoundaryReach( const Float &radius )
|
||||||
|
{
|
||||||
|
this->handler->presence[this->ref].radius = radius; // * this->handler->data[this->ref].scale;
|
||||||
|
if( this->handler->data[this->ref].state != CollisionHandler<Entity>::Limbo )
|
||||||
|
this->handler->data[this->ref].state = CollisionHandler<Entity>::Changed; // TODO : implement a queue system
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
void CollisionHandler<Entity>::Reference::setPosition( const Float3 &position )
|
||||||
|
{
|
||||||
|
this->handler->presence[this->ref].center = position;
|
||||||
|
if( this->handler->data[this->ref].state != CollisionHandler<Entity>::Limbo )
|
||||||
|
this->handler->data[this->ref].state = CollisionHandler<Entity>::Changed; // TODO : implement a queue system
|
||||||
|
}
|
||||||
|
|
||||||
|
// template<typename Entity>
|
||||||
|
// void CollisionHandler<Entity>::Reference::setScale( const Float &scale )
|
||||||
|
// {
|
||||||
|
// this->handler->presence[this->ref].radius *= scale / this->handler->data[this->ref].scale;
|
||||||
|
// this->handler->data[this->ref].scale = scale;
|
||||||
|
//
|
||||||
|
// if( this->handler->data[this->ref].state != CollisionHandler<Entity>::Limbo )
|
||||||
|
// this->handler->data[this->ref].state = CollisionHandler<Entity>::Changed; // TODO : implement a queue system
|
||||||
|
// }
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
void CollisionHandler<Entity>::Reference::moveToLimbo( )
|
||||||
|
{ /* TODO : implement a limbo system */
|
||||||
|
this->handler->data[this->ref].state = CollisionHandler<Entity>::Limbo;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
void CollisionHandler<Entity>::Reference::leaveLimbo( )
|
||||||
|
{ /* TODO : implement a limbo system */
|
||||||
|
this->handler->data[this->ref].state = CollisionHandler<Entity>::Changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
bool CollisionHandler<Entity>::Reference::isActive( ) const
|
||||||
|
{
|
||||||
|
switch( this->handler->data[this->ref].state )
|
||||||
|
{
|
||||||
|
case Updated:
|
||||||
|
case Changed:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Entity>
|
||||||
|
bool CollisionHandler<Entity>::Reference::isInLimbo( ) const
|
||||||
|
{ return ( this->handler->data[this->ref].state == Limbo ); }
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1 @@
|
||||||
|
#include "GameObject.h"
|
|
@ -0,0 +1,22 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
// to be removed
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef OYSTER_GAME_GAMEOBJECT_H
|
||||||
|
#define OYSTER_GAME_GAMEOBJECT_H
|
||||||
|
|
||||||
|
#include "OysterMath.h"
|
||||||
|
|
||||||
|
namespace Oyster { namespace Game
|
||||||
|
{
|
||||||
|
class GameObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,119 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "MoveAble.h"
|
||||||
|
|
||||||
|
using namespace ::Oyster::Game;
|
||||||
|
using namespace ::Oyster::Math;
|
||||||
|
using namespace ::Oyster::Collision;
|
||||||
|
|
||||||
|
namespace PrivateStatic
|
||||||
|
{
|
||||||
|
Float timeSlice = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveAble::setDiscreteTimeSlice( const Float &seconds )
|
||||||
|
{ PrivateStatic::timeSlice = seconds; }
|
||||||
|
|
||||||
|
const Float & MoveAble::getDiscreteTimeSlice( )
|
||||||
|
{ return PrivateStatic::timeSlice; }
|
||||||
|
|
||||||
|
MoveAble::MoveAble( ) : body(Float4x4::identity, Float3(1.0f)), rotationPivot(Float3::null), speed(Float3::null), rotationalSpeed(Float3::null), acceleration(Float3::null), rotationalAcceleration(Float3::null)
|
||||||
|
{
|
||||||
|
this->speed = Float3::null;
|
||||||
|
}
|
||||||
|
|
||||||
|
MoveAble::MoveAble( const MoveAble &obj ) : body(obj.body), rotationPivot(obj.rotationPivot), speed(obj.speed), rotationalSpeed(obj.rotationalSpeed), acceleration(obj.acceleration), rotationalAcceleration(obj.rotationalAcceleration)
|
||||||
|
{
|
||||||
|
this->speed = obj.speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
MoveAble::MoveAble( const Float4x4 &orientation, const Float3 &_rotationPivot ) : body(orientation, Float3(1.0f)), rotationPivot(_rotationPivot), speed(Float3::null), rotationalSpeed(Float3::null), acceleration(Float3::null), rotationalAcceleration(Float3::null)
|
||||||
|
{
|
||||||
|
this->speed = Float3::null;
|
||||||
|
}
|
||||||
|
|
||||||
|
MoveAble::MoveAble( const Box &_body, const Float3 &_rotationPivot ) : body(_body), rotationPivot(_rotationPivot), speed(Float3::null), rotationalSpeed(Float3::null), acceleration(Float3::null), rotationalAcceleration(Float3::null)
|
||||||
|
{
|
||||||
|
this->speed = Float3::null;
|
||||||
|
}
|
||||||
|
|
||||||
|
MoveAble::~MoveAble( ) { /* Nothing needed here */ }
|
||||||
|
|
||||||
|
MoveAble & MoveAble::operator = ( const MoveAble &obj )
|
||||||
|
{
|
||||||
|
this->body = obj.body;
|
||||||
|
this->rotationPivot = obj.rotationPivot;
|
||||||
|
this->speed = obj.speed;
|
||||||
|
this->rotationalSpeed = obj.rotationalSpeed;
|
||||||
|
this->acceleration = obj.acceleration;
|
||||||
|
this->rotationalAcceleration = obj.rotationalAcceleration;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveAble::accelerate( const Float3 &deltaSpeed, const Float3 &lever )
|
||||||
|
{
|
||||||
|
this->acceleration += vectorProjection( deltaSpeed, lever );
|
||||||
|
this->rotationalAcceleration += deltaAngularAxis( deltaSpeed, lever );
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveAble::accelerate( const Float3 &deltaSpeed )
|
||||||
|
{ this->acceleration += deltaSpeed; }
|
||||||
|
|
||||||
|
void MoveAble::accelerateTurn( const Float3 &deltaAngularSpeed )
|
||||||
|
{ this->rotationalAcceleration += deltaAngularSpeed; }
|
||||||
|
|
||||||
|
void MoveAble::stop( )
|
||||||
|
{ this->speed = this->rotationalSpeed = Float3::null; }
|
||||||
|
|
||||||
|
void MoveAble::stopRotation( )
|
||||||
|
{ this->rotationalSpeed = Float3::null; }
|
||||||
|
|
||||||
|
void MoveAble::stopMovement( )
|
||||||
|
{ this->speed = Float3::null; }
|
||||||
|
|
||||||
|
void MoveAble::setSize( const Float3 &size )
|
||||||
|
{ this->body.boundingOffset = size * 0.5f; }
|
||||||
|
|
||||||
|
Float3 MoveAble::getSize( ) const
|
||||||
|
{ return this->body.boundingOffset * 2.0f; }
|
||||||
|
|
||||||
|
void MoveAble::setOrientation( const Float4x4 & orientation )
|
||||||
|
{
|
||||||
|
// if( (this->body.orientation.v[3].xyz - orientation.v[3].xyz).length() >= 500.0f )
|
||||||
|
// { // BUG HUNT illegal Teleportation trap
|
||||||
|
// const char * debug = "Illegal Teleportation Occured?";
|
||||||
|
// }
|
||||||
|
|
||||||
|
this->body.orientation = orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Float4x4 & MoveAble::getOrientation( ) const
|
||||||
|
{
|
||||||
|
return this->body.orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
Float3 MoveAble::getMovement( const Float3 &offset ) const
|
||||||
|
{ return this->speed + particleRotationMovement( this->rotationalSpeed, offset ); }
|
||||||
|
|
||||||
|
const Float3 & MoveAble::getMovement( ) const
|
||||||
|
{ return this->speed; }
|
||||||
|
|
||||||
|
const Float3 & MoveAble::getRotation( ) const
|
||||||
|
{ return this->rotationalSpeed; }
|
||||||
|
|
||||||
|
void MoveAble::update( )
|
||||||
|
{
|
||||||
|
this->speed += this->acceleration * PrivateStatic::timeSlice;
|
||||||
|
this->rotationalSpeed += this->rotationalAcceleration * PrivateStatic::timeSlice;
|
||||||
|
this->acceleration = this->rotationalAcceleration = Float3::null; // clearing acceleration every discrete timeslice (update)
|
||||||
|
|
||||||
|
Float4x4 m;
|
||||||
|
rigidBodyMatrix( m, this->rotationalSpeed * PrivateStatic::timeSlice,
|
||||||
|
( this->speed * PrivateStatic::timeSlice ) + this->body.orientation.v[3].xyz,
|
||||||
|
this->rotationPivot );
|
||||||
|
this->body.orientation.v[3].xyz = Float3::null;
|
||||||
|
|
||||||
|
transformMatrix( this->body.orientation, this->body.orientation, m );
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef GAME_MOVEABLE_H
|
||||||
|
#define GAME_MOVEABLE_H
|
||||||
|
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "OysterCollision.h"
|
||||||
|
|
||||||
|
namespace Oyster { namespace Game
|
||||||
|
{
|
||||||
|
class MoveAble
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void setDiscreteTimeSlice( const ::Oyster::Math::Float &seconds );
|
||||||
|
static const ::Oyster::Math::Float & getDiscreteTimeSlice( );
|
||||||
|
|
||||||
|
MoveAble( );
|
||||||
|
MoveAble( const MoveAble &obj );
|
||||||
|
MoveAble( const ::Oyster::Math::Float4x4 &orientation, const ::Oyster::Math::Float3 &rotationPivot = ::Oyster::Math::Float3::null );
|
||||||
|
MoveAble( const ::Oyster::Collision::Box &body, const ::Oyster::Math::Float3 &rotationPivot = ::Oyster::Math::Float3::null );
|
||||||
|
virtual ~MoveAble( );
|
||||||
|
|
||||||
|
virtual MoveAble & operator = ( const MoveAble &obj );
|
||||||
|
|
||||||
|
void accelerate( const ::Oyster::Math::Float3 &deltaSpeed, const ::Oyster::Math::Float3 &lever );
|
||||||
|
void accelerate( const ::Oyster::Math::Float3 &deltaSpeed );
|
||||||
|
void accelerateTurn( const ::Oyster::Math::Float3 &deltaRotationalSpeed );
|
||||||
|
|
||||||
|
void stop( );
|
||||||
|
void stopRotation( );
|
||||||
|
void stopMovement( );
|
||||||
|
|
||||||
|
void setSize( const ::Oyster::Math::Float3 &size );
|
||||||
|
::Oyster::Math::Float3 getSize( ) const;
|
||||||
|
|
||||||
|
virtual void setOrientation( const ::Oyster::Math::Float4x4 & orientation );
|
||||||
|
const ::Oyster::Math::Float4x4 & getOrientation( ) const;
|
||||||
|
|
||||||
|
::Oyster::Math::Float3 getMovement( const ::Oyster::Math::Float3 &offset ) const;
|
||||||
|
const ::Oyster::Math::Float3 & getMovement( ) const;
|
||||||
|
const ::Oyster::Math::Float3 & getRotation( ) const;
|
||||||
|
|
||||||
|
virtual void update( );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
::Oyster::Collision::Box body;
|
||||||
|
::Oyster::Math::Float3 rotationPivot;
|
||||||
|
|
||||||
|
::Oyster::Math::Float3 speed, rotationalSpeed;
|
||||||
|
::Oyster::Math::Float3 acceleration, rotationalAcceleration;
|
||||||
|
};
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,3 @@
|
||||||
|
#include "MoveAble.h"
|
||||||
|
#include "CollisionHandler.h"
|
||||||
|
#include "SateliteCamera.h"
|
|
@ -0,0 +1,307 @@
|
||||||
|
#include "SateliteCamera.h"
|
||||||
|
|
||||||
|
using namespace Oyster::Game;
|
||||||
|
using namespace Oyster::Math;
|
||||||
|
using namespace Oyster::Collision;
|
||||||
|
|
||||||
|
namespace PrivateStatic
|
||||||
|
{
|
||||||
|
inline void towardsZero( Float &target, const Float &maxStep )
|
||||||
|
{
|
||||||
|
if( target > maxStep ) target -= maxStep;
|
||||||
|
else if( target < -maxStep ) target += maxStep;
|
||||||
|
else target = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SateliteCamera::SateliteCamera( const Float4x4 *rigidBody, const Float3 &offsetPos, const Float3 &upVector, const Float4x4 &_projection )
|
||||||
|
: offsetRadian(Float3::null), offsetPan(Float3::null), offsetDistance(0.0f), focus(rigidBody),
|
||||||
|
defaultRelation(Float4x4::identity), projection(_projection), view(), viewProjection(),
|
||||||
|
sampler(), viewIsOutOfDate(true), viewProjectionIsOutOfDate(true), samplerIsOutOfDate(true)
|
||||||
|
{
|
||||||
|
this->defaultRelation.v[3].xyz = offsetPos;
|
||||||
|
this->defaultRelation.v[2].xyz = offsetPos.getNormalized() * -1.0f;
|
||||||
|
this->defaultRelation.v[1].xyz = (upVector - ( this->defaultRelation.v[2].xyz * this->defaultRelation.v[2].xyz.dot(upVector) )).getNormalized();
|
||||||
|
this->defaultRelation.v[0].xyz = this->defaultRelation.v[1].xyz.cross( this->defaultRelation.v[2].xyz );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::setFocus( const Float4x4 *rigidBody, const Float3 &offsetPos, const Float3 &upVector )
|
||||||
|
{
|
||||||
|
this->defaultRelation.v[3].xyz = offsetPos;
|
||||||
|
this->defaultRelation.v[2].xyz = offsetPos.getNormalized();
|
||||||
|
this->defaultRelation.v[1].xyz = (upVector - ( this->defaultRelation.v[2].xyz * this->defaultRelation.v[2].xyz.dot(upVector) )).getNormalized();
|
||||||
|
this->defaultRelation.v[0].xyz = this->defaultRelation.v[1].xyz.cross( this->defaultRelation.v[2].xyz );
|
||||||
|
this->defaultRelation.v[2].xyz *= -1.0f;
|
||||||
|
|
||||||
|
this->focus = rigidBody;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::setProjection( const Float4x4 &transform )
|
||||||
|
{
|
||||||
|
this->projection = transform;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ::Oyster::Math::Float4x4 & SateliteCamera::getView( ) const
|
||||||
|
{
|
||||||
|
// if( this->viewIsOutOfDate )
|
||||||
|
{
|
||||||
|
Float4x4 world = this->defaultRelation;
|
||||||
|
|
||||||
|
if( this->offsetDistance != 0.0f )
|
||||||
|
world.v[3].xyz += world.v[2].xyz * this->offsetDistance;
|
||||||
|
|
||||||
|
if( this->offsetRadian != Float3::null || this->offsetPan != Float3::null )
|
||||||
|
{
|
||||||
|
Float4x4 m;
|
||||||
|
rigidBodyMatrix( m, this->offsetRadian, offsetPan );
|
||||||
|
transformMatrix( world, world, m );
|
||||||
|
}
|
||||||
|
|
||||||
|
transformMatrix( world, world, *this->focus );
|
||||||
|
inverseRigidBodyMatrix( this->view, world );
|
||||||
|
|
||||||
|
this->viewIsOutOfDate = false;
|
||||||
|
}
|
||||||
|
return this->view;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Float4x4 & SateliteCamera::getProjection( ) const
|
||||||
|
{ return this->projection; }
|
||||||
|
|
||||||
|
const Float4x4 & SateliteCamera::getViewProjection( ) const
|
||||||
|
{
|
||||||
|
// if( this->viewProjectionIsOutOfDate )
|
||||||
|
{
|
||||||
|
viewProjectionMatrix( this->viewProjection, this->getView(), this->projection );
|
||||||
|
this->viewProjectionIsOutOfDate = false;
|
||||||
|
}
|
||||||
|
return this->viewProjection;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Frustrum & SateliteCamera::getSampler( ) const
|
||||||
|
{
|
||||||
|
if( this->samplerIsOutOfDate )
|
||||||
|
{
|
||||||
|
this->sampler = this->getViewProjection();
|
||||||
|
this->samplerIsOutOfDate = false;
|
||||||
|
}
|
||||||
|
return this->sampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::revolveLeft( const Float &deltaRadian )
|
||||||
|
{
|
||||||
|
this->offsetRadian.y += deltaRadian;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::revolveRight( const Float &deltaRadian )
|
||||||
|
{
|
||||||
|
this->offsetRadian.y -= deltaRadian;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::revolveUp( const Float &deltaRadian )
|
||||||
|
{
|
||||||
|
this->offsetRadian.x += deltaRadian;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::revolveDown( const Float &deltaRadian )
|
||||||
|
{
|
||||||
|
this->offsetRadian.x -= deltaRadian;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::revolveRollLeft( const Float &deltaRadian )
|
||||||
|
{
|
||||||
|
this->offsetRadian.z += deltaRadian;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::revolveRollRight( const Float &deltaRadian )
|
||||||
|
{
|
||||||
|
this->offsetRadian.z -= deltaRadian;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::setHorizontalRevolution( const Float &radian )
|
||||||
|
{
|
||||||
|
this->offsetRadian.y = radian;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::setVerticalRevolution( const Float &radian )
|
||||||
|
{
|
||||||
|
this->offsetRadian.x = radian;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::setRollRevolution( const Float &radian )
|
||||||
|
{
|
||||||
|
this->offsetRadian.z = radian;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::moveIn( const Float &deltaLength )
|
||||||
|
{
|
||||||
|
this->offsetDistance -= deltaLength;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::moveOut( const Float &deltaLength )
|
||||||
|
{
|
||||||
|
this->offsetDistance += deltaLength;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::panForward( const Float &deltaLength )
|
||||||
|
{
|
||||||
|
this->offsetPan.z += deltaLength;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::panBackward( const Float &deltaLength )
|
||||||
|
{
|
||||||
|
this->offsetPan.z -= deltaLength;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::panLeft( const Float &deltaLength )
|
||||||
|
{
|
||||||
|
this->offsetPan.x -= deltaLength;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::panRight( const Float &deltaLength )
|
||||||
|
{
|
||||||
|
this->offsetPan.x += deltaLength;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::panUp( const Float &deltaLength )
|
||||||
|
{
|
||||||
|
this->offsetPan.y += deltaLength;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::panDown( const Float &deltaLength )
|
||||||
|
{
|
||||||
|
this->offsetPan.y -= deltaLength;
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::stabiliseRoll( const Float &deltaRadian )
|
||||||
|
{
|
||||||
|
if( this->offsetRadian.z != 0.0f )
|
||||||
|
{
|
||||||
|
PrivateStatic::towardsZero( this->offsetRadian.z, deltaRadian );
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::stabiliseHorizontally( const Float &deltaRadian )
|
||||||
|
{
|
||||||
|
if( this->offsetRadian.y != 0.0f )
|
||||||
|
{
|
||||||
|
PrivateStatic::towardsZero( this->offsetRadian.y, deltaRadian );
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::stabiliseVertically( const Float &deltaRadian )
|
||||||
|
{
|
||||||
|
if( this->offsetRadian.x != 0.0f )
|
||||||
|
{
|
||||||
|
PrivateStatic::towardsZero( this->offsetRadian.x, deltaRadian );
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::stabiliseDistance( const Float &deltaLength )
|
||||||
|
{
|
||||||
|
if( this->offsetDistance != 0.0f )
|
||||||
|
{
|
||||||
|
PrivateStatic::towardsZero( this->offsetDistance, deltaLength );
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::stabilisePanX( const Float &deltaLength )
|
||||||
|
{
|
||||||
|
if( this->offsetPan.x != 0.0f )
|
||||||
|
{
|
||||||
|
PrivateStatic::towardsZero( this->offsetPan.x, deltaLength );
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::stabilisePanY( const Float &deltaLength )
|
||||||
|
{
|
||||||
|
if( this->offsetPan.y != 0.0f )
|
||||||
|
{
|
||||||
|
PrivateStatic::towardsZero( this->offsetPan.y, deltaLength );
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SateliteCamera::stabilisePanZ( const Float &deltaLength )
|
||||||
|
{
|
||||||
|
if( this->offsetPan.z != 0.0f )
|
||||||
|
{
|
||||||
|
PrivateStatic::towardsZero( this->offsetPan.z, deltaLength );
|
||||||
|
this->viewIsOutOfDate = true;
|
||||||
|
this->viewProjectionIsOutOfDate = true;
|
||||||
|
this->samplerIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/*
|
||||||
|
Target use is by example tail camera, 3rd person perspective
|
||||||
|
and such.
|
||||||
|
*/
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef OYSTER_GAME_SATELITECAMERA_H
|
||||||
|
#define OYSTER_GAME_SATELITECAMERA_H
|
||||||
|
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "Frustrum.h"
|
||||||
|
|
||||||
|
namespace Oyster { namespace Game
|
||||||
|
{
|
||||||
|
class SateliteCamera
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SateliteCamera( const ::Oyster::Math::Float4x4 *rigidBody, const ::Oyster::Math::Float3 &offsetPos, const ::Oyster::Math::Float3 &upVector, const ::Oyster::Math::Float4x4 &projection );
|
||||||
|
|
||||||
|
void setFocus( const ::Oyster::Math::Float4x4 *rigidBody, const ::Oyster::Math::Float3 &offsetPos, const ::Oyster::Math::Float3 &upVector );
|
||||||
|
void setProjection( const ::Oyster::Math::Float4x4 &transform );
|
||||||
|
|
||||||
|
const ::Oyster::Math::Float4x4 & getView( ) const;
|
||||||
|
const ::Oyster::Math::Float4x4 & getProjection( ) const;
|
||||||
|
const ::Oyster::Math::Float4x4 & getViewProjection( ) const;
|
||||||
|
const ::Oyster::Collision::Frustrum & getSampler( ) const;
|
||||||
|
|
||||||
|
void revolveLeft( const ::Oyster::Math::Float &deltaRadian );
|
||||||
|
void revolveRight( const ::Oyster::Math::Float &deltaRadian );
|
||||||
|
void revolveUp( const ::Oyster::Math::Float &deltaRadian );
|
||||||
|
void revolveDown( const ::Oyster::Math::Float &deltaRadian );
|
||||||
|
void revolveRollLeft( const ::Oyster::Math::Float &deltaRadian );
|
||||||
|
void revolveRollRight( const ::Oyster::Math::Float &deltaRadian );
|
||||||
|
void setHorizontalRevolution( const ::Oyster::Math::Float &radian );
|
||||||
|
void setVerticalRevolution( const ::Oyster::Math::Float &radian );
|
||||||
|
void setRollRevolution( const ::Oyster::Math::Float &radian );
|
||||||
|
|
||||||
|
void moveIn( const ::Oyster::Math::Float &deltaLength );
|
||||||
|
void moveOut( const ::Oyster::Math::Float &deltaLength );
|
||||||
|
|
||||||
|
void panForward( const ::Oyster::Math::Float &deltaLength );
|
||||||
|
void panBackward( const ::Oyster::Math::Float &deltaLength );
|
||||||
|
void panLeft( const ::Oyster::Math::Float &deltaLength );
|
||||||
|
void panRight( const ::Oyster::Math::Float &deltaLength );
|
||||||
|
void panUp( const ::Oyster::Math::Float &deltaLength );
|
||||||
|
void panDown( const ::Oyster::Math::Float &deltaLength );
|
||||||
|
|
||||||
|
void stabiliseRoll( const ::Oyster::Math::Float &deltaRadian );
|
||||||
|
void stabiliseHorizontally( const ::Oyster::Math::Float &deltaRadian );
|
||||||
|
void stabiliseVertically( const ::Oyster::Math::Float &deltaRadian );
|
||||||
|
void stabiliseDistance( const ::Oyster::Math::Float &deltaLength );
|
||||||
|
void stabilisePanX( const ::Oyster::Math::Float &deltaLength );
|
||||||
|
void stabilisePanY( const ::Oyster::Math::Float &deltaLength );
|
||||||
|
void stabilisePanZ( const ::Oyster::Math::Float &deltaLength );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
mutable ::Oyster::Math::Float3 offsetRadian;
|
||||||
|
mutable ::Oyster::Math::Float3 offsetPan;
|
||||||
|
mutable ::Oyster::Math::Float offsetDistance;
|
||||||
|
private:
|
||||||
|
const ::Oyster::Math::Float4x4 *focus;
|
||||||
|
::Oyster::Math::Float4x4 defaultRelation, projection;
|
||||||
|
mutable ::Oyster::Math::Float4x4 view, viewProjection;
|
||||||
|
mutable ::Oyster::Collision::Frustrum sampler;
|
||||||
|
mutable bool viewIsOutOfDate, viewProjectionIsOutOfDate, samplerIsOutOfDate;
|
||||||
|
};
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,284 @@
|
||||||
|
#include "InputController.h"
|
||||||
|
using namespace Oyster::Input;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool keys[256] = {0};
|
||||||
|
bool prevs[256]= {0};
|
||||||
|
bool mouse[5] = {0};
|
||||||
|
bool mPrev[5] = {0};
|
||||||
|
int XPos,YPos,PrevX,PrevY,DeltaX,DeltaY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::KeyPressed(const WPARAM &Key)
|
||||||
|
{
|
||||||
|
prevs[Key]=false;
|
||||||
|
keys[Key]=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::KeyReleased(const WPARAM &Key)
|
||||||
|
{
|
||||||
|
prevs[Key]=true;
|
||||||
|
keys[Key] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Controller::isKeyDown(const WPARAM &Key)
|
||||||
|
{
|
||||||
|
return keys[Key];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Controller::isKeyPressed(const WPARAM &Key)
|
||||||
|
{
|
||||||
|
if(keys[Key] && !prevs[Key])
|
||||||
|
{
|
||||||
|
prevs[Key] = keys[Key];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Controller::isKeyReleased(const WPARAM &Key)
|
||||||
|
{
|
||||||
|
if(!keys[Key] && prevs[Key])
|
||||||
|
{
|
||||||
|
prevs[Key] = keys[Key];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::MouseBtnPressed(const WPARAM &btn)
|
||||||
|
{
|
||||||
|
switch(btn)
|
||||||
|
{
|
||||||
|
case MK_LBUTTON:
|
||||||
|
mouse[0] = true;
|
||||||
|
mPrev[0] = false;
|
||||||
|
break;
|
||||||
|
case MK_RBUTTON:
|
||||||
|
mouse[1] = true;
|
||||||
|
mPrev[1] = false;
|
||||||
|
break;
|
||||||
|
case MK_MBUTTON:
|
||||||
|
mouse[2] = true;
|
||||||
|
mPrev[2] = false;
|
||||||
|
break;
|
||||||
|
case MK_XBUTTON1:
|
||||||
|
mouse[3] = true;
|
||||||
|
mPrev[3] = false;
|
||||||
|
break;
|
||||||
|
case MK_XBUTTON2:
|
||||||
|
mouse[4] = true;
|
||||||
|
mPrev[4] = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::MouseBtnReleased(const WPARAM &btn)
|
||||||
|
{
|
||||||
|
switch(btn)
|
||||||
|
{
|
||||||
|
case MK_LBUTTON:
|
||||||
|
mouse[0] = false;
|
||||||
|
mPrev[0] = true;
|
||||||
|
break;
|
||||||
|
case MK_RBUTTON:
|
||||||
|
mouse[1] = false;
|
||||||
|
mPrev[1] = true;
|
||||||
|
break;
|
||||||
|
case MK_MBUTTON:
|
||||||
|
mouse[2] = false;
|
||||||
|
mPrev[2] = true;
|
||||||
|
break;
|
||||||
|
case MK_XBUTTON1:
|
||||||
|
mouse[3] = false;
|
||||||
|
mPrev[3] = true;
|
||||||
|
break;
|
||||||
|
case MK_XBUTTON2:
|
||||||
|
mouse[4] = false;
|
||||||
|
mPrev[4] = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Controller::isMouseBtnDown(const WPARAM &Btn)
|
||||||
|
{
|
||||||
|
switch(Btn)
|
||||||
|
{
|
||||||
|
case MK_LBUTTON:
|
||||||
|
return mouse[0];
|
||||||
|
case MK_RBUTTON:
|
||||||
|
return mouse[1];
|
||||||
|
case MK_MBUTTON:
|
||||||
|
return mouse[2];
|
||||||
|
case MK_XBUTTON1:
|
||||||
|
return mouse[3];
|
||||||
|
case MK_XBUTTON2:
|
||||||
|
return mouse[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Controller::isMouseBtnPressed(const WPARAM &Btn)
|
||||||
|
{
|
||||||
|
switch(Btn)
|
||||||
|
{
|
||||||
|
case MK_LBUTTON:
|
||||||
|
if(mouse[0] && !mPrev[0])
|
||||||
|
{
|
||||||
|
mPrev[0] = mouse[0];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case MK_RBUTTON:
|
||||||
|
if(mouse[1] && !mPrev[1])
|
||||||
|
{
|
||||||
|
mPrev[1] = mouse[1];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case MK_MBUTTON:
|
||||||
|
if(mouse[2] && !mPrev[2])
|
||||||
|
{
|
||||||
|
mPrev[2] = mouse[2];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case MK_XBUTTON1:
|
||||||
|
if(mouse[3] && !mPrev[3])
|
||||||
|
{
|
||||||
|
mPrev[3] = mouse[3];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case MK_XBUTTON2:
|
||||||
|
if(mouse[4] && !mPrev[4])
|
||||||
|
{
|
||||||
|
mPrev[4] = mouse[4];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Controller::isMouseBtnReleased(const WPARAM &Btn)
|
||||||
|
{
|
||||||
|
switch(Btn)
|
||||||
|
{
|
||||||
|
case MK_LBUTTON:
|
||||||
|
if(!mouse[0] && mPrev[0])
|
||||||
|
{
|
||||||
|
mPrev[0] = mouse[0];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case MK_RBUTTON:
|
||||||
|
if(!mouse[1] && mPrev[1])
|
||||||
|
{
|
||||||
|
mPrev[1] = mouse[1];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case MK_MBUTTON:
|
||||||
|
if(!mouse[2] && mPrev[2])
|
||||||
|
{
|
||||||
|
mPrev[2] = mouse[2];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case MK_XBUTTON1:
|
||||||
|
if(!mouse[3] && mPrev[3])
|
||||||
|
{
|
||||||
|
mPrev[3] = mouse[3];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case MK_XBUTTON2:
|
||||||
|
if(!mouse[4] && mPrev[4])
|
||||||
|
{
|
||||||
|
mPrev[4] = mouse[4];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::MouseMove(int x,int y)
|
||||||
|
{
|
||||||
|
PrevY = YPos;
|
||||||
|
PrevX = XPos;
|
||||||
|
XPos = x;
|
||||||
|
YPos = y;
|
||||||
|
DeltaY = YPos - PrevY;
|
||||||
|
DeltaX = XPos - PrevX;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Controller::GetY()
|
||||||
|
{
|
||||||
|
return YPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Controller::GetX()
|
||||||
|
{
|
||||||
|
return XPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Controller::GetAnalogX()
|
||||||
|
{
|
||||||
|
float f = (float)XPos;
|
||||||
|
f /=( Window::Size.left/2);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Controller::GetAnalogY()
|
||||||
|
{
|
||||||
|
float f = (float)YPos;
|
||||||
|
f /=( Window::Size.top/2);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Controller::GetDeltaY()
|
||||||
|
{
|
||||||
|
return DeltaY;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Controller::GetDeltaX()
|
||||||
|
{
|
||||||
|
return DeltaX;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::ResetDeltaX()
|
||||||
|
{
|
||||||
|
DeltaX = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::ResetDeltaY()
|
||||||
|
{
|
||||||
|
DeltaY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::RestrictMouse(bool restrict)
|
||||||
|
{
|
||||||
|
Oyster::Window::CaptureMouse(restrict);
|
||||||
|
}
|
||||||
|
|
||||||
|
//sets x=0,y=0 to be the center oc the client area
|
||||||
|
void Controller::OrigoCenter()
|
||||||
|
{
|
||||||
|
int x = Window::Size.left/2;
|
||||||
|
int y = Window::Size.top/2;
|
||||||
|
|
||||||
|
Window::SetMouseOffset(-x,-y);
|
||||||
|
}
|
||||||
|
|
||||||
|
//default
|
||||||
|
void Controller::OrigoTopLeft()
|
||||||
|
{
|
||||||
|
Oyster::Window::SetMouseOffset(0,0);
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef InputController_H
|
||||||
|
#define InputController_H
|
||||||
|
|
||||||
|
#include "../Window/Window.h"
|
||||||
|
//READ http://msdn.microsoft.com/en-us/library/windows/desktop/ms648380(v=vs.85).aspx#_win32_Confining_a_Cursor
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
class Window;
|
||||||
|
namespace Input
|
||||||
|
{
|
||||||
|
class Controller
|
||||||
|
{
|
||||||
|
friend class ::Oyster::Window;
|
||||||
|
private:
|
||||||
|
//Keybord events from Oyster::Window
|
||||||
|
static void KeyPressed(const WPARAM &Key);
|
||||||
|
//Keybord events from Oyster::Window
|
||||||
|
static void KeyReleased(const WPARAM &Key);
|
||||||
|
|
||||||
|
|
||||||
|
//Mouse events from Oyster::Window
|
||||||
|
static void MouseMove(int x,int y);
|
||||||
|
//Mouse events from Oyster::Window
|
||||||
|
static void MouseBtnPressed(const WPARAM &Btn);
|
||||||
|
static void MouseBtnReleased(const WPARAM &Btn);
|
||||||
|
public:
|
||||||
|
//Polling Functions
|
||||||
|
static bool isKeyDown(const WPARAM &Key);
|
||||||
|
static bool isKeyPressed(const WPARAM &Key);
|
||||||
|
static bool isKeyReleased(const WPARAM &Key);
|
||||||
|
|
||||||
|
static bool isMouseBtnDown(const WPARAM &Btn);
|
||||||
|
static bool isMouseBtnPressed(const WPARAM &Btn);
|
||||||
|
static bool isMouseBtnReleased(const WPARAM &Btn);
|
||||||
|
|
||||||
|
static int GetX();
|
||||||
|
static int GetY();
|
||||||
|
|
||||||
|
static float GetAnalogX();
|
||||||
|
static float GetAnalogY();
|
||||||
|
|
||||||
|
static int GetDeltaX();
|
||||||
|
static int GetDeltaY();
|
||||||
|
|
||||||
|
//Controll Functions
|
||||||
|
static void ResetDeltaX();
|
||||||
|
static void ResetDeltaY();
|
||||||
|
|
||||||
|
//off by default
|
||||||
|
static void RestrictMouse(bool b = true);
|
||||||
|
|
||||||
|
//sets x=0,y=0 to be the center oc the client area
|
||||||
|
static void OrigoCenter();
|
||||||
|
|
||||||
|
//default
|
||||||
|
static void OrigoTopLeft();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,268 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Collection of Linear Math Stuff
|
||||||
|
// © Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef LINEARMATH_H
|
||||||
|
#define LINEARMATH_H
|
||||||
|
|
||||||
|
#include "Vector.h"
|
||||||
|
#include "Matrix.h"
|
||||||
|
#include "Quaternion.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
namespace LinearAlgebra
|
||||||
|
{
|
||||||
|
// x2
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType> operator * ( const Matrix2x2<ElementType> &left, const Matrix2x2<ElementType> &right )
|
||||||
|
{ return Matrix2x2<ElementType>( (left.m11 * right.m11) + (left.m21 * right.m12), (left.m11 * right.m21) + (left.m21 * right.m22), (left.m12 * right.m11) + (left.m22 * right.m12), (left.m12 * right.m21) + (left.m22 * right.m22) ); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector2<ElementType> operator * ( const Matrix2x2<ElementType> &matrix, const Vector2<ElementType> &vector )
|
||||||
|
{ return Vector2<ElementType>( (matrix.m11 * vector.x) + (matrix.m21 * vector.y), (matrix.m12 * vector.x) + (matrix.m22 * vector.y) ); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector2<ElementType> operator * ( const Vector2<ElementType> &vector, const Matrix2x2<ElementType> &left )
|
||||||
|
{ return Vector2<ElementType>( (vector.x * matrix.m11) + (vector.y * matrix.m12), (vector.x * matrix.m21) + (vector.y * matrix.m22) ); }
|
||||||
|
|
||||||
|
// x3
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType> operator * ( const Matrix3x3<ElementType> &left, const Matrix3x3<ElementType> &right )
|
||||||
|
{
|
||||||
|
Matrix3x3<ElementType> product, leftT = left.getTranspose();
|
||||||
|
for( int i = 0; i < 3; ++i ) for( int j = 0; j < 3; ++j )
|
||||||
|
product.m[i][j] = leftT.v[i].dot(right.v[j]);
|
||||||
|
return product;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector3<ElementType> operator * ( const Matrix3x3<ElementType> &matrix, const Vector3<ElementType> &vector )
|
||||||
|
{ return Vector3<ElementType>( (matrix.m11 * vector.x) + (matrix.m21 * vector.y) + (matrix.m31 * vector.z), (matrix.m12 * vector.x) + (matrix.m22 * vector.y) + (matrix.m32 * vector.z), (matrix.m13 * vector.x) + (matrix.m23 * vector.y) + (matrix.m33 * vector.z) ); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector3<ElementType> operator * ( const Vector3<ElementType> &vector, const Matrix3x3<ElementType> &left )
|
||||||
|
{ return Vector3<ElementType>( (vector.x * matrix.m11) + (vector.y * matrix.m12) + (vector.z * matrix.m13), (vector.x * matrix.m21) + (vector.y * matrix.m22) + (vector.z * matrix.m23), (vector.x * matrix.m31) + (vector.y * matrix.m32) + (vector.z * matrix.m33) ); }
|
||||||
|
|
||||||
|
// x4
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType> operator * ( const Matrix4x4<ElementType> &left, const Matrix4x4<ElementType> &right )
|
||||||
|
{
|
||||||
|
Matrix4x4<ElementType> product, rightT = right.getTranspose();
|
||||||
|
for( int i = 0; i < 4; ++i )
|
||||||
|
{
|
||||||
|
product.m[i][0] = left.v[i].dot(rightT.v[0]);
|
||||||
|
product.m[i][1] = left.v[i].dot(rightT.v[1]);
|
||||||
|
product.m[i][2] = left.v[i].dot(rightT.v[2]);
|
||||||
|
product.m[i][3] = left.v[i].dot(rightT.v[3]);
|
||||||
|
}
|
||||||
|
return product;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector4<ElementType> operator * ( const Matrix4x4<ElementType> &matrix, const Vector4<ElementType> &vector )
|
||||||
|
{ return Vector4<ElementType>( (matrix.m11 * vector.x) + (matrix.m21 * vector.y) + (matrix.m31 * vector.z) + (matrix.m41 * vector.w), (matrix.m12 * vector.x) + (matrix.m22 * vector.y) + (matrix.m32 * vector.z) + (matrix.m42 * vector.w), (matrix.m13 * vector.x) + (matrix.m23 * vector.y) + (matrix.m33 * vector.z) + (matrix.m43 * vector.w), (matrix.m14 * vector.x) + (matrix.m24 * vector.y) + (matrix.m34 * vector.z) + (matrix.m44 * vector.w) ); }
|
||||||
|
|
||||||
|
template<typename ElementType> // works for column weighted matrixes
|
||||||
|
Vector4<ElementType> operator * ( const Vector4<ElementType> &vector, const Matrix4x4<ElementType> &matrix )
|
||||||
|
{ return Vector4<ElementType>( (vector.x * matrix.m11) + (vector.y * matrix.m12) + (vector.z * matrix.m13) + (vector.w * matrix.m14), (vector.x * matrix.m21) + (vector.y * matrix.m22) + (vector.z * matrix.m23) + (vector.w * matrix.m24), (vector.x * matrix.m31) + (vector.y * matrix.m32) + (vector.z * matrix.m33) + (vector.w * matrix.m34), (vector.x * matrix.m41) + (vector.y * matrix.m42) + (vector.z * matrix.m43) + (vector.w * matrix.m44) ); }
|
||||||
|
|
||||||
|
namespace _2D
|
||||||
|
{
|
||||||
|
template<typename ElementType>
|
||||||
|
inline void translationMatrix( Matrix3x3<ElementType> &output, const Vector2<ElementType> &position )
|
||||||
|
// { output = Matrix3x3<ElementType>( 1, 0, position.x, 0, 1, position.y, 0, 0, 1 ); }
|
||||||
|
{ output = Matrix3x3<ElementType>( 1, 0, 0, 0, 1, 0, position.x, position.y, 1 ); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
void rotationMatrix( Matrix2x2<ElementType> &output, const ElementType &radian )
|
||||||
|
{
|
||||||
|
ElementType s = std::sin( radian ),
|
||||||
|
c = std::cos( radian );
|
||||||
|
// output = Matrix2x2<ElementType>( c, -s, s, c );
|
||||||
|
output = Matrix2x2<ElementType>( c, s, -s, c );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
void rotationMatrix( Matrix3x3<ElementType> &output, const ElementType &radian )
|
||||||
|
{
|
||||||
|
ElementType s = std::sin( radian ),
|
||||||
|
c = std::cos( radian );
|
||||||
|
// output = Matrix3x3<ElementType>( c, -s, 0, s, c, 0, 0, 0, 1 );
|
||||||
|
output = Matrix3x3<ElementType>( c, s, 0, -s, c, 0, 0, 0, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
void rigidBodyMatrix( Matrix3x3<ElementType> &output, const ElementType &radian, const Vector2<ElementType> &position )
|
||||||
|
{
|
||||||
|
ElementType s = std::sin( radian ),
|
||||||
|
c = std::cos( radian );
|
||||||
|
// output = Matrix3x3<ElementType>( c, -s, position.x, s, c, position.y, 0, 0, 1 );
|
||||||
|
output = Matrix3x3<ElementType>( c, s, 0, -s, c, 0, position.x, position.y, 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace _3D
|
||||||
|
{
|
||||||
|
template<typename ElementType>
|
||||||
|
inline void translationMatrix( Matrix4x4<ElementType> &output, const Vector3<ElementType> &position )
|
||||||
|
// { output = Matrix4x4<ElementType>( 1, 0, 0, position.x, 0, 1, 0, position.y, 0, 0, 1, position.z, 0, 0, 0, 1 ); }
|
||||||
|
{ output = Matrix4x4<ElementType>( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, position.x, position.y, position.z, 1 ); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
void inverseRigidBody( Matrix4x4<ElementType> &output, const Matrix4x4<ElementType> &rigidBody )
|
||||||
|
{
|
||||||
|
output = Matrix4x4<ElementType>( rigidBody.m11, rigidBody.m21, rigidBody.m31, 0,
|
||||||
|
rigidBody.m12, rigidBody.m22, rigidBody.m32, 0,
|
||||||
|
rigidBody.m13, rigidBody.m23, rigidBody.m33, 0,
|
||||||
|
-rigidBody.v[3].xyz.dot(rigidBody.v[0].xyz),
|
||||||
|
-rigidBody.v[3].xyz.dot(rigidBody.v[1].xyz),
|
||||||
|
-rigidBody.v[3].xyz.dot(rigidBody.v[2].xyz), 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
void rotationMatrix_AxisX( Matrix3x3<ElementType> &output, const ElementType &radian )
|
||||||
|
{
|
||||||
|
ElementType s = std::sin( radian ),
|
||||||
|
c = std::cos( radian );
|
||||||
|
// output = Matrix3x3<ElementType>( 1, 0, 0, 0, c, -s, 0, s, c );
|
||||||
|
output = Matrix3x3<ElementType>( 1, 0, 0, 0, c, s, 0, -s, c );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
void rotationMatrix_AxisX( Matrix4x4<ElementType> &output, const ElementType &radian )
|
||||||
|
{
|
||||||
|
ElementType s = std::sin( radian ),
|
||||||
|
c = std::cos( radian );
|
||||||
|
// output = Matrix4x4<ElementType>( 1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1 );
|
||||||
|
output = Matrix4x4<ElementType>( 1, 0, 0, 0, 0, c, s, 0, 0, -s, c, 0, 0, 0, 0, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
void rotationMatrix_AxisY( Matrix3x3<ElementType> &output, const ElementType &radian )
|
||||||
|
{
|
||||||
|
ElementType s = std::sin( radian ),
|
||||||
|
c = std::cos( radian );
|
||||||
|
// output = Matrix3x3<ElementType>( c, 0, s, 0, 1, 0, -s, 0, c );
|
||||||
|
output = Matrix3x3<ElementType>( c, 0, -s, 0, 1, 0, s, 0, c );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
void rotationMatrix_AxisY( Matrix4x4<ElementType> &output, const ElementType &radian )
|
||||||
|
{
|
||||||
|
ElementType s = std::sin( radian ),
|
||||||
|
c = std::cos( radian );
|
||||||
|
// output = Matrix4x4<ElementType>( c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1 );
|
||||||
|
output = Matrix4x4<ElementType>( c, 0, -s, 0, 0, 1, 0, 0, s, 0, c, 0, 0, 0, 0, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline void rotationMatrix_AxisZ( Matrix3x3<ElementType> &output, const ElementType &radian )
|
||||||
|
{ ::LinearAlgebra::_2D::rotationMatrix( output, radian ); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
void rotationMatrix_AxisZ( Matrix4x4<ElementType> &output, const ElementType &radian )
|
||||||
|
{
|
||||||
|
ElementType s = std::sin( radian ),
|
||||||
|
c = std::cos( radian );
|
||||||
|
// output = Matrix4x4<ElementType>( c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 );
|
||||||
|
output = Matrix4x4<ElementType>( c, s, 0, 0, -s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
void rotationMatrix( Matrix4x4<ElementType> &output, const Vector3<ElementType> &normalizedAxis, const ElementType &radian )
|
||||||
|
{ // TODO : Optimize
|
||||||
|
ElementType r = radian * 0.5f,
|
||||||
|
s = std::sin( r ),
|
||||||
|
c = std::cos( r );
|
||||||
|
Quaternion<ElementType> q( normalizedAxis * s, c ),
|
||||||
|
qConj = q.getConjugate();
|
||||||
|
|
||||||
|
output.v[0] = Vector4<ElementType>( (q*Vector3<ElementType>(1,0,0)*qConj).imaginary, 0 );
|
||||||
|
output.v[1] = Vector4<ElementType>( (q*Vector3<ElementType>(0,1,0)*qConj).imaginary, 0 );
|
||||||
|
output.v[2] = Vector4<ElementType>( (q*Vector3<ElementType>(0,0,1)*qConj).imaginary, 0 );
|
||||||
|
output.v[3] = Vector4<ElementType>( 0, 0, 0, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
returns a deltaAngularAxis which is a vectorProduct of the movementVector and leverVector.
|
||||||
|
angular: (1/I) * L, there I is known as the "moment of inertia", L as the "angular momentum vector".
|
||||||
|
lever: Displacement vector relative to the rotation pivot.
|
||||||
|
Recommended reading: http://en.wikipedia.org/wiki/Torque
|
||||||
|
*/
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector3<ElementType> deltaAngularAxis( const Vector3<ElementType> &movement, const Vector3<ElementType> &lever )
|
||||||
|
{ return movement.cross( lever ); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector3<ElementType> particleRotationMovement( const Vector3<ElementType> &deltaRadian, const Vector3<ElementType> &lever )
|
||||||
|
{ return lever.cross(deltaRadian) /= lever.dot(lever); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector3<ElementType> vectorProjection( const Vector3<ElementType> &vector, const Vector3<ElementType> &axis )
|
||||||
|
{ return axis * ( vector.dot(axis) / axis.dot(axis) ); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
output; is set to a rigibody matrix that revolve/rotate around centerOfMass and then translates.
|
||||||
|
sumDeltaAngularAxis: Sum of all ( (1/I) * ( L x D ) )-vectorproducts. There I is known as "moment of inertia", L as "angular momentum vector" and D the "lever vector".
|
||||||
|
sumTranslation: Sum of all the translation vectors.
|
||||||
|
centerOfMass: The point the particles is to revolve around, prior to translation. Default set to null vector aka origo.
|
||||||
|
Recommended reading: http://en.wikipedia.org/wiki/Torque
|
||||||
|
*/
|
||||||
|
template<typename ElementType>
|
||||||
|
void rigidBodyMatrix( Matrix4x4<ElementType> &output, const Vector3<ElementType> &sumDeltaAngularAxis, const Vector3<ElementType> &sumTranslation, const Vector3<ElementType> ¢erOfMass = Vector3<ElementType>::null )
|
||||||
|
{
|
||||||
|
ElementType deltaRadian = sumDeltaAngularAxis.length();
|
||||||
|
if( deltaRadian != 0 )
|
||||||
|
{
|
||||||
|
Vector3<ElementType> axis = sumDeltaAngularAxis / deltaRadian;
|
||||||
|
rotationMatrix( output, axis, deltaRadian );
|
||||||
|
|
||||||
|
output.v[3].xyz = centerOfMass;
|
||||||
|
output.v[3].x -= centerOfMass.dot( output.v[0].xyz );
|
||||||
|
output.v[3].y -= centerOfMass.dot( output.v[1].xyz );
|
||||||
|
output.v[3].z -= centerOfMass.dot( output.v[2].xyz );
|
||||||
|
}
|
||||||
|
else output = Matrix4x4<ElementType>::identity;
|
||||||
|
|
||||||
|
output.v[3].xyz += sumTranslation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
output; is set to an orthographic projection matrix.
|
||||||
|
width; of the projection sample volume.
|
||||||
|
height; of the projection sample volume.
|
||||||
|
nearClip: Distance to the nearClippingPlane.
|
||||||
|
farClip: Distance to the farClippingPlane
|
||||||
|
*/
|
||||||
|
template<typename ElementType>
|
||||||
|
void projectionMatrix_Orthographic( Matrix4x4<ElementType> &output, const ElementType &width, const ElementType &height, const ElementType &nearClip, const ElementType &farClip )
|
||||||
|
{
|
||||||
|
ElementType c = 1;
|
||||||
|
c /= nearClip - farClip;
|
||||||
|
output = Matrix4x4<ElementType>( 2/width, 0, 0, 0,
|
||||||
|
0, 2/height, 0, 0,
|
||||||
|
0, 0, -c, 0, 0,
|
||||||
|
0, nearClip*c, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
output; is set to a perspective transform matrix.
|
||||||
|
vertFoV; is the vertical field of vision in radians. (se FoV Hor+ )
|
||||||
|
aspect; is the screenratio width/height (example 16/9 or 16/10 )
|
||||||
|
nearClip: Distance to the nearClippingPlane
|
||||||
|
farClip: Distance to the farClippingPlane
|
||||||
|
*/
|
||||||
|
template<typename ElementType>
|
||||||
|
void projectionMatrix_Perspective( Matrix4x4<ElementType> &output, const ElementType &vertFoV, const ElementType &aspect, const ElementType &nearClip, const ElementType &farClip )
|
||||||
|
{
|
||||||
|
ElementType fov = 1 / ::std::tan( vertFoV * 0.5f ),
|
||||||
|
dDepth = farClip;
|
||||||
|
dDepth /= farClip - nearClip;
|
||||||
|
output = Matrix4x4<ElementType>( fov / aspect, 0, 0, 0, 0, fov, 0, 0, 0, 0, dDepth, 1, 0, 0, -(dDepth * nearClip), 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,761 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Linear Math Matrixes
|
||||||
|
// Š Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef LINEARALGEBRA_MATRIX_H
|
||||||
|
#define LINEARALGEBRA_MATRIX_H
|
||||||
|
|
||||||
|
#include "Vector.h"
|
||||||
|
#include "Utilities.h"
|
||||||
|
|
||||||
|
namespace LinearAlgebra
|
||||||
|
{
|
||||||
|
template<typename ElementType>
|
||||||
|
class Matrix2x2
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
union
|
||||||
|
{
|
||||||
|
ElementType m[2][2];
|
||||||
|
struct{ Vector2<ElementType> v[2]; };
|
||||||
|
// struct{ ElementType m11, m21, m12, m22; };
|
||||||
|
struct{ ElementType m11, m12, m21, m22; };
|
||||||
|
ElementType element[4];
|
||||||
|
char byte[sizeof(ElementType[4])];
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Matrix2x2<ElementType> identity, null;
|
||||||
|
|
||||||
|
Matrix2x2( );
|
||||||
|
Matrix2x2( const ElementType &m11, const ElementType &m12,
|
||||||
|
const ElementType &m21, const ElementType &m22 );
|
||||||
|
Matrix2x2( const Vector2<ElementType> vec[2] );
|
||||||
|
Matrix2x2( const Vector2<ElementType> &vec1, const Vector2<ElementType> &vec2 );
|
||||||
|
Matrix2x2( const ElementType element[4] );
|
||||||
|
Matrix2x2( const Matrix2x2<ElementType> &matrix );
|
||||||
|
|
||||||
|
operator ElementType* ( );
|
||||||
|
operator const ElementType* ( ) const;
|
||||||
|
|
||||||
|
Matrix2x2<ElementType> & operator = ( const Vector2<ElementType> vec[2] );
|
||||||
|
Matrix2x2<ElementType> & operator = ( const ElementType element[4] );
|
||||||
|
Matrix2x2<ElementType> & operator = ( const Matrix2x2<ElementType> &matrix );
|
||||||
|
Matrix2x2<ElementType> & operator += ( const Matrix2x2<ElementType> &matrix );
|
||||||
|
Matrix2x2<ElementType> & operator -= ( const Matrix2x2<ElementType> &matrix );
|
||||||
|
Matrix2x2<ElementType> & operator *= ( const ElementType &scalar );
|
||||||
|
Matrix2x2<ElementType> & operator /= ( const ElementType &scalar );
|
||||||
|
Matrix2x2<ElementType> operator + ( const Matrix2x2<ElementType> &matrix ) const;
|
||||||
|
Matrix2x2<ElementType> operator - ( const Matrix2x2<ElementType> &matrix ) const;
|
||||||
|
Matrix2x2<ElementType> operator * ( const ElementType &scalar ) const;
|
||||||
|
Matrix2x2<ElementType> operator / ( const ElementType &scalar ) const;
|
||||||
|
Matrix2x2<ElementType> operator - ( ) const; // unary negation
|
||||||
|
|
||||||
|
ElementType getDeterminant( ) const;
|
||||||
|
Matrix2x2<ElementType> getAdjoint( ) const;
|
||||||
|
Matrix2x2<ElementType> getTranspose( ) const;
|
||||||
|
Matrix2x2<ElementType> & transpose( );
|
||||||
|
Matrix2x2<ElementType> getInverse( ) const;
|
||||||
|
Matrix2x2<ElementType> getInverse( ElementType &determinant ) const;
|
||||||
|
Matrix2x2<ElementType> & invert( );
|
||||||
|
Matrix2x2<ElementType> & invert( ElementType &determinant );
|
||||||
|
Vector2<ElementType> getRowVector( unsigned int rowID ) const;
|
||||||
|
const Vector2<ElementType> & getColumnVector( unsigned int colID ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
class Matrix3x3
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
union
|
||||||
|
{
|
||||||
|
ElementType m[3][3];
|
||||||
|
struct{ Vector3<ElementType> v[3]; };
|
||||||
|
// struct{ ElementType m11, m21, m31, m12, m22, m32, m13, m23, m33; };
|
||||||
|
struct{ ElementType m11, m12, m13, m21, m22, m23, m31, m32, m33; };
|
||||||
|
ElementType element[9];
|
||||||
|
char byte[sizeof(ElementType[9])];
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Matrix3x3<ElementType> identity, null;
|
||||||
|
|
||||||
|
Matrix3x3( );
|
||||||
|
Matrix3x3( const ElementType &m11, const ElementType &m12, const ElementType &m13,
|
||||||
|
const ElementType &m21, const ElementType &m22, const ElementType &m23,
|
||||||
|
const ElementType &m31, const ElementType &m32, const ElementType &m33 );
|
||||||
|
Matrix3x3( const Vector3<ElementType> vec[3] );
|
||||||
|
Matrix3x3( const Vector3<ElementType> &vec1, const Vector3<ElementType> &vec2, const Vector3<ElementType> &vec3 );
|
||||||
|
Matrix3x3( const ElementType element[9] );
|
||||||
|
Matrix3x3( const Matrix3x3<ElementType> &matrix );
|
||||||
|
|
||||||
|
operator ElementType* ( );
|
||||||
|
operator const ElementType* ( ) const;
|
||||||
|
|
||||||
|
Matrix3x3<ElementType> & operator = ( const Vector3<ElementType> vec[3] );
|
||||||
|
Matrix3x3<ElementType> & operator = ( const ElementType element[9] );
|
||||||
|
Matrix3x3<ElementType> & operator = ( const Matrix3x3<ElementType> &matrix );
|
||||||
|
Matrix3x3<ElementType> & operator += ( const Matrix3x3<ElementType> &matrix );
|
||||||
|
Matrix3x3<ElementType> & operator -= ( const Matrix3x3<ElementType> &matrix );
|
||||||
|
Matrix3x3<ElementType> & operator *= ( const ElementType &scalar );
|
||||||
|
Matrix3x3<ElementType> & operator /= ( const ElementType &scalar );
|
||||||
|
Matrix3x3<ElementType> operator + ( const Matrix3x3<ElementType> &matrix ) const;
|
||||||
|
Matrix3x3<ElementType> operator - ( const Matrix3x3<ElementType> &matrix ) const;
|
||||||
|
Matrix3x3<ElementType> operator * ( const ElementType &scalar ) const;
|
||||||
|
Matrix3x3<ElementType> operator / ( const ElementType &scalar ) const;
|
||||||
|
Matrix3x3<ElementType> operator - ( ) const; // unary negation
|
||||||
|
|
||||||
|
ElementType getDeterminant( ) const;
|
||||||
|
Matrix3x3<ElementType> getAdjoint( ) const;
|
||||||
|
Matrix3x3<ElementType> getTranspose( ) const;
|
||||||
|
Matrix3x3<ElementType> & transpose( );
|
||||||
|
Matrix3x3<ElementType> getInverse( ) const;
|
||||||
|
Matrix3x3<ElementType> getInverse( ElementType &determinant ) const;
|
||||||
|
Matrix3x3<ElementType> & invert( );
|
||||||
|
Matrix3x3<ElementType> & invert( ElementType &determinant );
|
||||||
|
Vector3<ElementType> getRowVector( unsigned int rowID ) const;
|
||||||
|
const Vector3<ElementType> & getColumnVector( unsigned int colID ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
class Matrix4x4
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
union
|
||||||
|
{
|
||||||
|
ElementType m[4][4];
|
||||||
|
struct{ Vector4<ElementType> v[4]; };
|
||||||
|
// struct{ ElementType m11, m21, m31, m41, m12, m22, m32, m42, m13, m23, m33, m43, m14, m24, m34, m44; };
|
||||||
|
struct{ ElementType m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44; };
|
||||||
|
ElementType element[16];
|
||||||
|
char byte[sizeof(ElementType[16])];
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Matrix4x4<ElementType> identity, null;
|
||||||
|
|
||||||
|
Matrix4x4( );
|
||||||
|
Matrix4x4( const ElementType &m11, const ElementType &m12, const ElementType &m13, const ElementType &m14,
|
||||||
|
const ElementType &m21, const ElementType &m22, const ElementType &m23, const ElementType &m24,
|
||||||
|
const ElementType &m31, const ElementType &m32, const ElementType &m33, const ElementType &m34,
|
||||||
|
const ElementType &m41, const ElementType &m42, const ElementType &m43, const ElementType &m44 );
|
||||||
|
Matrix4x4( const Vector4<ElementType> vec[4] );
|
||||||
|
Matrix4x4( const Vector4<ElementType> &vec1, const Vector4<ElementType> &vec2, const Vector4<ElementType> &vec3, const Vector4<ElementType> &vec4 );
|
||||||
|
Matrix4x4( const ElementType element[16] );
|
||||||
|
Matrix4x4( const Matrix4x4<ElementType> &matrix );
|
||||||
|
|
||||||
|
operator ElementType* ( );
|
||||||
|
operator const ElementType* ( ) const;
|
||||||
|
|
||||||
|
Matrix4x4<ElementType> & operator = ( const Vector4<ElementType> vec[4] );
|
||||||
|
Matrix4x4<ElementType> & operator = ( const ElementType element[16] );
|
||||||
|
Matrix4x4<ElementType> & operator = ( const Matrix4x4<ElementType> &matrix );
|
||||||
|
Matrix4x4<ElementType> & operator += ( const Matrix4x4<ElementType> &matrix );
|
||||||
|
Matrix4x4<ElementType> & operator -= ( const Matrix4x4<ElementType> &matrix );
|
||||||
|
Matrix4x4<ElementType> & operator *= ( const ElementType &scalar );
|
||||||
|
Matrix4x4<ElementType> & operator /= ( const ElementType &scalar );
|
||||||
|
Matrix4x4<ElementType> operator + ( const Matrix4x4<ElementType> &matrix ) const;
|
||||||
|
Matrix4x4<ElementType> operator - ( const Matrix4x4<ElementType> &matrix ) const;
|
||||||
|
Matrix4x4<ElementType> operator * ( const ElementType &scalar ) const;
|
||||||
|
Matrix4x4<ElementType> operator / ( const ElementType &scalar ) const;
|
||||||
|
Matrix4x4<ElementType> operator - ( ) const; // unary negation
|
||||||
|
|
||||||
|
ElementType getDeterminant( ) const;
|
||||||
|
Matrix4x4<ElementType> getAdjoint( ) const;
|
||||||
|
Matrix4x4<ElementType> getTranspose( ) const;
|
||||||
|
Matrix4x4<ElementType> & transpose( );
|
||||||
|
Matrix4x4<ElementType> getInverse( ) const;
|
||||||
|
Matrix4x4<ElementType> getInverse( ElementType &determinant ) const;
|
||||||
|
Matrix4x4<ElementType> & invert( );
|
||||||
|
Matrix4x4<ElementType> & invert( ElementType &determinant );
|
||||||
|
Vector4<ElementType> getRowVector( unsigned int rowID ) const;
|
||||||
|
const Vector4<ElementType> & getColumnVector( unsigned int colID ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Body
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Matrix2x2<ElementType> ///////////////////////////////////////
|
||||||
|
template<typename ElementType>
|
||||||
|
const Matrix2x2<ElementType> Matrix2x2<ElementType>::identity = Matrix2x2<ElementType>( 1, 0, 0, 1 );
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
const Matrix2x2<ElementType> Matrix2x2<ElementType>::null = Matrix2x2<ElementType>( 0, 0, 0, 0 );
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType>::Matrix2x2( ) : m11(0), m21(0), m12(0), m22(0) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType>::Matrix2x2( const ElementType &_m11, const ElementType &_m12, const ElementType &_m21, const ElementType &_m22 )
|
||||||
|
: m11(_m11), m21(_m21), m12(_m12), m22(_m22) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType>::Matrix2x2( const Vector2<ElementType> vec[2] )
|
||||||
|
: m11(vec[0].x), m21(vec[0].y), m12(vec[1].x), m22(vec[1].y) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType>::Matrix2x2( const Vector2<ElementType> &vec1, const Vector2<ElementType> &vec2 )
|
||||||
|
: m11(vec1.x), m21(vec1.y), m12(vec2.x), m22(vec2.y) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType>::Matrix2x2( const ElementType _element[4] )
|
||||||
|
// : m11(_element[0]), m21(_element[1]), m12(_element[2]), m22(_element[3]) {}
|
||||||
|
: m11(_element[0]), m12(_element[1]), m21(_element[2]), m22(_element[3]) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType>::Matrix2x2( const Matrix2x2<ElementType> &matrix )
|
||||||
|
: m11(matrix.m11), m21(matrix.m12), m12(matrix.m21), m22(matrix.m22) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix2x2<ElementType>::operator ElementType* ( )
|
||||||
|
{ return this->element; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix2x2<ElementType>::operator const ElementType* ( ) const
|
||||||
|
{ return this->element; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType> & Matrix2x2<ElementType>::operator = ( const Vector2<ElementType> vec[2] )
|
||||||
|
{
|
||||||
|
this->v[0] = vec[0];
|
||||||
|
this->v[1] = vec[1];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType> & Matrix2x2<ElementType>::operator = ( const ElementType element[4] )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 4; ++i )
|
||||||
|
this->element[i] = element[i];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType> & Matrix2x2<ElementType>::operator = ( const Matrix2x2<ElementType> &matrix )
|
||||||
|
{
|
||||||
|
this->v[0] = matrix.v[0];
|
||||||
|
this->v[1] = matrix.v[1];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType> & Matrix2x2<ElementType>::operator += ( const Matrix2x2<ElementType> &matrix )
|
||||||
|
{
|
||||||
|
this->v[0] += matrix.v[0];
|
||||||
|
this->v[1] += matrix.v[1];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType> & Matrix2x2<ElementType>::operator -= ( const Matrix2x2<ElementType> &matrix )
|
||||||
|
{
|
||||||
|
this->v[0] -= matrix.v[0];
|
||||||
|
this->v[1] -= matrix.v[1];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType> & Matrix2x2<ElementType>::operator *= ( const ElementType &scalar )
|
||||||
|
{
|
||||||
|
this->v[0] *= scalar;
|
||||||
|
this->v[1] *= scalar;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType> & Matrix2x2<ElementType>::operator /= ( const ElementType &scalar )
|
||||||
|
{
|
||||||
|
this->v[0] /= scalar;
|
||||||
|
this->v[1] /= scalar;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix2x2<ElementType> Matrix2x2<ElementType>::operator + ( const Matrix2x2<ElementType> &matrix ) const
|
||||||
|
{ return Matrix2x2<ElementType>(*this) += matrix; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix2x2<ElementType> Matrix2x2<ElementType>::operator - ( const Matrix2x2<ElementType> &matrix ) const
|
||||||
|
{ return Matrix2x2<ElementType>(*this) -= matrix; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix2x2<ElementType> Matrix2x2<ElementType>::operator * ( const ElementType &scalar ) const
|
||||||
|
{ return Matrix2x2<ElementType>(*this) *= scalar; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix2x2<ElementType> Matrix2x2<ElementType>::operator / ( const ElementType &scalar ) const
|
||||||
|
{ return Matrix2x2<ElementType>(*this) /= scalar; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix2x2<ElementType> Matrix2x2<ElementType>::operator - ( ) const
|
||||||
|
{ return Matrix2x2<ElementType>(-this->v[0], -this->v[1]); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
ElementType Matrix2x2<ElementType>::getDeterminant( ) const
|
||||||
|
{
|
||||||
|
ElementType determinant = (this->m11 * this->m22);
|
||||||
|
return determinant -= (this->m12 * this->m21);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType> Matrix2x2<ElementType>::getAdjoint( ) const
|
||||||
|
{ return Matrix2x2<ElementType>( this->m22, -this->m21, -this->m12, this->m11 ); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix2x2<ElementType> Matrix2x2<ElementType>::getTranspose( ) const
|
||||||
|
{ return Matrix2x2<ElementType>( this->element[0], this->element[1], this->element[2], this->element[3] ); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType> & Matrix2x2<ElementType>::transpose( )
|
||||||
|
{
|
||||||
|
ElementType swapSpace;
|
||||||
|
Utility::Element::swap( this->m12, this->m21, swapSpace );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix2x2<ElementType> Matrix2x2<ElementType>::getInverse( ) const
|
||||||
|
{ return this->getAdjoint() /= this->getDeterminant(); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType> Matrix2x2<ElementType>::getInverse( ElementType &determinant ) const
|
||||||
|
{
|
||||||
|
determinant = this->getDeterminant();
|
||||||
|
if( determinant != 0 )
|
||||||
|
return this->getAdjoint() / determinant;
|
||||||
|
return Matrix2x2<ElementType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType> & Matrix2x2<ElementType>::invert( )
|
||||||
|
{
|
||||||
|
*this /= this->getDeterminant();
|
||||||
|
this->m12 *= -1; this->m21 *= -1;
|
||||||
|
|
||||||
|
ElementType swapSpace;
|
||||||
|
Utility::Element::swap( this->m12, this->m21, swapSpace );
|
||||||
|
Utility::Element::swap( this->m11, this->m22, swapSpace );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix2x2<ElementType> & Matrix2x2<ElementType>::invert( ElementType &determinant )
|
||||||
|
{
|
||||||
|
determinant = this->getDeterminant();
|
||||||
|
|
||||||
|
if( determinant != 0 )
|
||||||
|
{
|
||||||
|
*this /= determinant;
|
||||||
|
this->m12 *= -1; this->m21 *= -1;
|
||||||
|
|
||||||
|
ElementType swapSpace;
|
||||||
|
Utility::Element::swap( this->m12, this->m21, swapSpace );
|
||||||
|
Utility::Element::swap( this->m11, this->m22, swapSpace );
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector2<ElementType> Matrix2x2<ElementType>::getRowVector( unsigned int rowID ) const
|
||||||
|
{ return Vector2<ElementType>( this->m[0][rowID], this->m[1][rowID] ); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline const Vector2<ElementType> & Matrix2x2<ElementType>::getColumnVector( unsigned int colID ) const
|
||||||
|
{ return this->v[colID]; }
|
||||||
|
|
||||||
|
// Matrix3x3<ElementType> ///////////////////////////////////////
|
||||||
|
template<typename ElementType>
|
||||||
|
const Matrix3x3<ElementType> Matrix3x3<ElementType>::identity = Matrix3x3<ElementType>( 1, 0, 0, 0, 1, 0, 0, 0, 1 );
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
const Matrix3x3<ElementType> Matrix3x3<ElementType>::null = Matrix3x3<ElementType>( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType>::Matrix3x3( ) : m11(0), m21(0), m31(0), m12(0), m22(0), m32(0), m13(0), m23(0), m33(0) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType>::Matrix3x3( const ElementType &_m11, const ElementType &_m12, const ElementType &_m13, const ElementType &_m21, const ElementType &_m22, const ElementType &_m23, const ElementType &_m31, const ElementType &_m32, const ElementType &_m33 )
|
||||||
|
: m11(_m11), m21(_m21), m31(_m31), m12(_m12), m22(_m22), m32(_m32), m13(_m13), m23(_m23), m33(_m33) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType>::Matrix3x3( const Vector3<ElementType> vec[3] )
|
||||||
|
: m11(vec[0].x), m21(vec[0].y), m31(vec[0].z), m12(vec[1].x), m22(vec[1].y), m32(vec[1].z), m13(vec[2].x), m23(vec[2].y), m33(vec[2].z) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType>::Matrix3x3( const Vector3<ElementType> &vec1, const Vector3<ElementType> &vec2, const Vector3<ElementType> &vec3 )
|
||||||
|
: m11(vec1.x), m21(vec1.y), m31(vec1.z), m12(vec2.x), m22(vec2.y), m32(vec2.z), m13(vec3.x), m23(vec3.y), m33(vec3.z) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType>::Matrix3x3( const ElementType _element[9] )
|
||||||
|
// : m11(_element[0]), m21(_element[1]), m31(_element[2]), m12(_element[3]), m22(_element[4]), m32(_element[5]), m13(_element[6]), m23(_element[7]), m33(_element[8]) {}
|
||||||
|
: m11(_element[0]), m12(_element[1]), m13(_element[2]), m21(_element[3]), m22(_element[4]), m23(_element[5]), m31(_element[6]), m32(_element[7]), m33(_element[8]) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType>::Matrix3x3( const Matrix3x3<ElementType> &matrix )
|
||||||
|
: m11(matrix.m11), m21(matrix.m21), m31(matrix.m31), m12(matrix.m12), m22(matrix.m22), m32(matrix.m32), m13(matrix.m13), m23(matrix.m23), m33(matrix.m33) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix3x3<ElementType>::operator ElementType* ( )
|
||||||
|
{ return this->element; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix3x3<ElementType>::operator const ElementType* ( ) const
|
||||||
|
{ return this->element; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType> & Matrix3x3<ElementType>::operator = ( const Vector3<ElementType> vec[3] )
|
||||||
|
{
|
||||||
|
this->v[0] = vec[0];
|
||||||
|
this->v[1] = vec[1];
|
||||||
|
this->v[2] = vec[2];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType> & Matrix3x3<ElementType>::operator = ( const ElementType element[9] )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 9; ++i )
|
||||||
|
this->element[i] = element[i];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType> & Matrix3x3<ElementType>::operator = ( const Matrix3x3<ElementType> &matrix )
|
||||||
|
{
|
||||||
|
this->v[0] = matrix.v[0];
|
||||||
|
this->v[1] = matrix.v[1];
|
||||||
|
this->v[2] = matrix.v[2];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType> & Matrix3x3<ElementType>::operator += ( const Matrix3x3<ElementType> &matrix )
|
||||||
|
{
|
||||||
|
this->v[0] += matrix.v[0];
|
||||||
|
this->v[1] += matrix.v[1];
|
||||||
|
this->v[2] += matrix.v[2];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType> & Matrix3x3<ElementType>::operator -= ( const Matrix3x3<ElementType> &matrix )
|
||||||
|
{
|
||||||
|
this->v[0] -= matrix.v[0];
|
||||||
|
this->v[1] -= matrix.v[1];
|
||||||
|
this->v[2] -= matrix.v[2];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType> & Matrix3x3<ElementType>::operator *= ( const ElementType &scalar )
|
||||||
|
{
|
||||||
|
this->v[0] *= scalar;
|
||||||
|
this->v[1] *= scalar;
|
||||||
|
this->v[2] *= scalar;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType> & Matrix3x3<ElementType>::operator /= ( const ElementType &scalar )
|
||||||
|
{
|
||||||
|
this->v[0] /= scalar;
|
||||||
|
this->v[1] /= scalar;
|
||||||
|
this->v[2] /= scalar;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix3x3<ElementType> Matrix3x3<ElementType>::operator + ( const Matrix3x3<ElementType> &matrix ) const
|
||||||
|
{ return Matrix3x3<ElementType>(*this) += matrix; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix3x3<ElementType> Matrix3x3<ElementType>::operator - ( const Matrix3x3<ElementType> &matrix ) const
|
||||||
|
{ return Matrix3x3<ElementType>(*this) -= matrix; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix3x3<ElementType> Matrix3x3<ElementType>::operator * ( const ElementType &scalar ) const
|
||||||
|
{ return Matrix3x3<ElementType>(*this) *= scalar; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix3x3<ElementType> Matrix3x3<ElementType>::operator / ( const ElementType &scalar ) const
|
||||||
|
{ return Matrix3x3<ElementType>(*this) /= scalar; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix3x3<ElementType> Matrix3x3<ElementType>::operator - ( ) const
|
||||||
|
{ return Matrix3x3<ElementType>(-this->v[0], -this->v[1], -this->v[2]); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
ElementType Matrix3x3<ElementType>::getDeterminant( ) const
|
||||||
|
{
|
||||||
|
ElementType determinant = (this->m11 * this->m22 * this->m33);
|
||||||
|
determinant += (this->m12 * this->m23 * this->m31);
|
||||||
|
determinant += (this->m13 * this->m21 * this->m32);
|
||||||
|
determinant -= (this->m11 * this->m23 * this->m32);
|
||||||
|
determinant -= (this->m12 * this->m21 * this->m33);
|
||||||
|
return determinant -= (this->m13 * this->m22 * this->m31);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType> Matrix3x3<ElementType>::getAdjoint( ) const
|
||||||
|
{
|
||||||
|
return Matrix3x3<ElementType>( (this->m22*this->m33 - this->m23*this->m32), (this->m13*this->m32 - this->m12*this->m33), (this->m12*this->m23 - this->m13*this->m22),
|
||||||
|
(this->m23*this->m31 - this->m21*this->m33), (this->m11*this->m33 - this->m13*this->m31), (this->m13*this->m21 - this->m11*this->m23),
|
||||||
|
(this->m21*this->m32 - this->m22*this->m31), (this->m12*this->m31 - this->m11*this->m32), (this->m11*this->m22 - this->m12*this->m21) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix3x3<ElementType> Matrix3x3<ElementType>::getTranspose( ) const
|
||||||
|
{
|
||||||
|
return Matrix3x3<ElementType>( this->m11, this->m21, this->m31,
|
||||||
|
this->m12, this->m22, this->m32,
|
||||||
|
this->m13, this->m23, this->m33 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType> & Matrix3x3<ElementType>::transpose( )
|
||||||
|
{
|
||||||
|
ElementType swapSpace;
|
||||||
|
Utility::Element::swap( this->m12, this->m21, swapSpace );
|
||||||
|
Utility::Element::swap( this->m13, this->m31, swapSpace );
|
||||||
|
Utility::Element::swap( this->m23, this->m32, swapSpace );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType> Matrix3x3<ElementType>::getInverse( ) const
|
||||||
|
{ return this->getAdjoint() /= this->getDeterminant(); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType> Matrix3x3<ElementType>::getInverse( ElementType &determinant ) const
|
||||||
|
{
|
||||||
|
determinant = this->getDeterminant();
|
||||||
|
if( determinant != 0 )
|
||||||
|
return this->getAdjoint() /= determinant;
|
||||||
|
else return Matrix3x3<ElementType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType> & Matrix3x3<ElementType>::invert( )
|
||||||
|
{ return *this = this->getAdjoint() /= this->getDeterminant(); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix3x3<ElementType> & Matrix3x3<ElementType>::invert( ElementType &determinant )
|
||||||
|
{
|
||||||
|
determinant = this->getDeterminant();
|
||||||
|
if( determinant != 0 )
|
||||||
|
return *this = this->getAdjoint() /= determinant;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector3<ElementType> Matrix3x3<ElementType>::getRowVector( unsigned int rowID ) const
|
||||||
|
{ return Vector3<ElementType>( this->m[0][rowID], this->m[1][rowID], this->m[2][rowID] ); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline const Vector3<ElementType> & Matrix3x3<ElementType>::getColumnVector( unsigned int colID ) const
|
||||||
|
{ return this->v[colID]; }
|
||||||
|
|
||||||
|
// Matrix4x4<ElementType> ///////////////////////////////////////
|
||||||
|
template<typename ElementType>
|
||||||
|
const Matrix4x4<ElementType> Matrix4x4<ElementType>::identity = Matrix4x4<ElementType>( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 );
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
const Matrix4x4<ElementType> Matrix4x4<ElementType>::null = Matrix4x4<ElementType>( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType>::Matrix4x4( )
|
||||||
|
: m11(0), m21(0), m31(0), m41(0), m12(0), m22(0), m32(0), m42(0), m13(0), m23(0), m33(0), m43(0), m14(0), m24(0), m34(0), m44(0) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType>::Matrix4x4( const ElementType &_m11, const ElementType &_m12, const ElementType &_m13, const ElementType &_m14, const ElementType &_m21, const ElementType &_m22, const ElementType &_m23, const ElementType &_m24, const ElementType &_m31, const ElementType &_m32, const ElementType &_m33, const ElementType &_m34, const ElementType &_m41, const ElementType &_m42, const ElementType &_m43, const ElementType &_m44 )
|
||||||
|
: m11(_m11), m21(_m21), m31(_m31), m41(_m41), m12(_m12), m22(_m22), m32(_m32), m42(_m42), m13(_m13), m23(_m23), m33(_m33), m43(_m43), m14(_m14), m24(_m24), m34(_m34), m44(_m44) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType>::Matrix4x4( const Vector4<ElementType> vec[4] )
|
||||||
|
: m11(vec[0].x), m21(vec[0].y), m31(vec[0].z), m41(vec[0].w), m12(vec[1].x), m22(vec[1].y), m32(vec[1].z), m42(vec[1].w), m13(vec[2].x), m23(vec[2].y), m33(vec[2].z), m43(vec[2].w), m14(vec[3].x), m24(vec[3].y), m34(vec[3].z), m44(vec[3].w) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType>::Matrix4x4( const Vector4<ElementType> &vec1, const Vector4<ElementType> &vec2, const Vector4<ElementType> &vec3, const Vector4<ElementType> &vec4 )
|
||||||
|
: m11(vec1.x), m21(vec1.y), m31(vec1.z), m41(vec1.w), m12(vec2.x), m22(vec2.y), m32(vec2.z), m42(vec2.w), m13(vec3.x), m23(vec3.y), m33(vec3.z), m43(vec3.w), m14(vec4.x), m24(vec4.y), m34(vec4.z), m44(vec4.w) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType>::Matrix4x4( const ElementType _element[16] )
|
||||||
|
// : m11(_element[0]), m21(_element[1]), m31(_element[2]), m41(_element[3]), m12(_element[4]), m22(_element[5]), m32(_element[6]), m42(_element[7]), m13(_element[8]), m23(_element[9]), m33(_element[10]), m43(_element[11]), m14(_element[12]), m24(_element[13]), m34(_element[14]), m44(_element[15]) {}
|
||||||
|
: m11(_element[0]), m12(_element[1]), m13(_element[2]), m14(_element[3]), m21(_element[4]), m22(_element[5]), m23(_element[6]), m24(_element[7]), m31(_element[8]), m32(_element[9]), m33(_element[10]), m34(_element[11]), m41(_element[12]), m42(_element[13]), m43(_element[14]), m44(_element[15]) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType>::Matrix4x4( const Matrix4x4<ElementType> &matrix )
|
||||||
|
: m11(matrix.m11), m21(matrix.m21), m31(matrix.m31), m41(matrix.m41), m12(matrix.m12), m22(matrix.m22), m32(matrix.m32), m42(matrix.m42), m13(matrix.m13), m23(matrix.m23), m33(matrix.m33), m43(matrix.m43), m14(matrix.m14), m24(matrix.m24), m34(matrix.m34), m44(matrix.m44) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix4x4<ElementType>::operator ElementType* ( )
|
||||||
|
{ return this->element; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix4x4<ElementType>::operator const ElementType* ( ) const
|
||||||
|
{ return this->element; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType> & Matrix4x4<ElementType>::operator = ( const Vector4<ElementType> vec[4] )
|
||||||
|
{
|
||||||
|
this->v[0] = vec[0];
|
||||||
|
this->v[1] = vec[1];
|
||||||
|
this->v[2] = vec[2];
|
||||||
|
this->v[3] = vec[3];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType> & Matrix4x4<ElementType>::operator = ( const ElementType element[16] )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 16; ++i )
|
||||||
|
this->element[i] = element[i];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType> & Matrix4x4<ElementType>::operator = ( const Matrix4x4<ElementType> &matrix )
|
||||||
|
{
|
||||||
|
this->v[0] = matrix.v[0];
|
||||||
|
this->v[1] = matrix.v[1];
|
||||||
|
this->v[2] = matrix.v[2];
|
||||||
|
this->v[3] = matrix.v[3];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType> & Matrix4x4<ElementType>::operator += ( const Matrix4x4<ElementType> &matrix )
|
||||||
|
{
|
||||||
|
this->v[0] += matrix.v[0];
|
||||||
|
this->v[1] += matrix.v[1];
|
||||||
|
this->v[2] += matrix.v[2];
|
||||||
|
this->v[3] += matrix.v[3];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType> & Matrix4x4<ElementType>::operator -= ( const Matrix4x4<ElementType> &matrix )
|
||||||
|
{
|
||||||
|
this->v[0] -= matrix.v[0];
|
||||||
|
this->v[1] -= matrix.v[1];
|
||||||
|
this->v[2] -= matrix.v[2];
|
||||||
|
this->v[3] -= matrix.v[3];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType> & Matrix4x4<ElementType>::operator *= ( const ElementType &scalar )
|
||||||
|
{
|
||||||
|
this->v[0] *= scalar;
|
||||||
|
this->v[1] *= scalar;
|
||||||
|
this->v[2] *= scalar;
|
||||||
|
this->v[3] *= scalar;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType> & Matrix4x4<ElementType>::operator /= ( const ElementType &scalar )
|
||||||
|
{
|
||||||
|
this->v[0] /= scalar;
|
||||||
|
this->v[1] /= scalar;
|
||||||
|
this->v[2] /= scalar;
|
||||||
|
this->v[3] /= scalar;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix4x4<ElementType> Matrix4x4<ElementType>::operator + ( const Matrix4x4<ElementType> &matrix ) const
|
||||||
|
{ return Matrix4x4<ElementType>(*this) += matrix; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix4x4<ElementType> Matrix4x4<ElementType>::operator - ( const Matrix4x4<ElementType> &matrix ) const
|
||||||
|
{ return Matrix4x4<ElementType>(*this) -= matrix; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix4x4<ElementType> Matrix4x4<ElementType>::operator * ( const ElementType &scalar ) const
|
||||||
|
{ return Matrix4x4<ElementType>(*this) *= scalar; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix4x4<ElementType> Matrix4x4<ElementType>::operator / ( const ElementType &scalar ) const
|
||||||
|
{ return Matrix4x4<ElementType>(*this) /= scalar; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix4x4<ElementType> Matrix4x4<ElementType>::operator - ( ) const
|
||||||
|
{ return Matrix4x4<ElementType>(-this->v[0], -this->v[1], -this->v[2], -this->v[3]); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
ElementType Matrix4x4<ElementType>::getDeterminant( ) const
|
||||||
|
{
|
||||||
|
ElementType determinant = this->m11 * Matrix3x3<ElementType>(this->m22, this->m23, this->m24, this->m32, this->m33, this->m34, this->m42, this->m43, this->m44).getDeterminant();
|
||||||
|
determinant -= this->m12 * Matrix3x3<ElementType>(this->m21, this->m23, this->m24, this->m31, this->m33, this->m34, this->m41, this->m43, this->m44).getDeterminant();
|
||||||
|
determinant += this->m13 * Matrix3x3<ElementType>(this->m21, this->m22, this->m24, this->m31, this->m32, this->m34, this->m41, this->m42, this->m44).getDeterminant();
|
||||||
|
return determinant -= this->m14 * Matrix3x3<ElementType>(this->m21, this->m22, this->m23, this->m31, this->m32, this->m33, this->m41, this->m42, this->m43).getDeterminant();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType> Matrix4x4<ElementType>::getAdjoint( ) const
|
||||||
|
{
|
||||||
|
return Matrix4x4<ElementType>( Matrix3x3<ElementType>(this->m22, this->m23, this->m24, this->m32, this->m33, this->m34, this->m42, this->m43, this->m44).getDeterminant(), -Matrix3x3<ElementType>(this->m12, this->m13, this->m14, this->m32, this->m33, this->m34, this->m42, this->m43, this->m44).getDeterminant(), Matrix3x3<ElementType>(this->m12, this->m13, this->m14, this->m22, this->m23, this->m24, this->m42, this->m43, this->m44).getDeterminant(), -Matrix3x3<ElementType>(this->m12, this->m13, this->m14, this->m22, this->m23, this->m24, this->m32, this->m33, this->m34).getDeterminant(),
|
||||||
|
-Matrix3x3<ElementType>(this->m21, this->m23, this->m24, this->m31, this->m33, this->m34, this->m41, this->m43, this->m44).getDeterminant(), Matrix3x3<ElementType>(this->m11, this->m13, this->m14, this->m31, this->m33, this->m34, this->m41, this->m43, this->m44).getDeterminant(), -Matrix3x3<ElementType>(this->m11, this->m13, this->m14, this->m21, this->m23, this->m24, this->m41, this->m43, this->m44).getDeterminant(), Matrix3x3<ElementType>(this->m11, this->m13, this->m14, this->m21, this->m23, this->m24, this->m31, this->m33, this->m34).getDeterminant(),
|
||||||
|
Matrix3x3<ElementType>(this->m21, this->m22, this->m24, this->m31, this->m32, this->m34, this->m41, this->m42, this->m44).getDeterminant(), -Matrix3x3<ElementType>(this->m11, this->m12, this->m14, this->m31, this->m32, this->m34, this->m41, this->m42, this->m44).getDeterminant(), Matrix3x3<ElementType>(this->m11, this->m12, this->m14, this->m21, this->m22, this->m24, this->m41, this->m42, this->m44).getDeterminant(), -Matrix3x3<ElementType>(this->m11, this->m12, this->m14, this->m21, this->m22, this->m24, this->m31, this->m32, this->m34).getDeterminant(),
|
||||||
|
-Matrix3x3<ElementType>(this->m21, this->m22, this->m23, this->m31, this->m32, this->m33, this->m41, this->m42, this->m43).getDeterminant(), Matrix3x3<ElementType>(this->m11, this->m12, this->m13, this->m31, this->m32, this->m33, this->m41, this->m42, this->m43).getDeterminant(), -Matrix3x3<ElementType>(this->m11, this->m12, this->m13, this->m21, this->m22, this->m23, this->m41, this->m42, this->m43).getDeterminant(), Matrix3x3<ElementType>(this->m11, this->m12, this->m13, this->m21, this->m22, this->m23, this->m31, this->m32, this->m33).getDeterminant() );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix4x4<ElementType> Matrix4x4<ElementType>::getTranspose( ) const
|
||||||
|
{
|
||||||
|
return Matrix4x4<ElementType>( this->m11, this->m21, this->m31, this->m41,
|
||||||
|
this->m12, this->m22, this->m32, this->m42,
|
||||||
|
this->m13, this->m23, this->m33, this->m43,
|
||||||
|
this->m14, this->m24, this->m34, this->m44 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType> & Matrix4x4<ElementType>::transpose( )
|
||||||
|
{
|
||||||
|
ElementType swapSpace;
|
||||||
|
::Utility::Element::swap( this->m12, this->m21, swapSpace );
|
||||||
|
::Utility::Element::swap( this->m13, this->m31, swapSpace );
|
||||||
|
::Utility::Element::swap( this->m14, this->m41, swapSpace );
|
||||||
|
::Utility::Element::swap( this->m23, this->m32, swapSpace );
|
||||||
|
::Utility::Element::swap( this->m24, this->m42, swapSpace );
|
||||||
|
::Utility::Element::swap( this->m34, this->m43, swapSpace );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Matrix4x4<ElementType> Matrix4x4<ElementType>::getInverse( ) const
|
||||||
|
{ return this->getAdjoint() /= this->getDeterminant() ; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType> Matrix4x4<ElementType>::getInverse( ElementType &determinant ) const
|
||||||
|
{
|
||||||
|
determinant = this->getDeterminant();
|
||||||
|
if( determinant != 0.0f )
|
||||||
|
return this->getAdjoint() /= determinant;
|
||||||
|
return Matrix4x4<ElementType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType> & Matrix4x4<ElementType>::invert( )
|
||||||
|
{ return *this = this->getAdjoint() /= this->getDeterminant(); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Matrix4x4<ElementType> & Matrix4x4<ElementType>::invert( ElementType &determinant )
|
||||||
|
{
|
||||||
|
determinant = this->getDeterminant();
|
||||||
|
if( determinant != 0.0f )
|
||||||
|
return *this = this->getAdjoint() /= determinant;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector4<ElementType> Matrix4x4<ElementType>::getRowVector( unsigned int rowID ) const
|
||||||
|
{ return Vector4<ElementType>( this->m[0][rowID], this->m[1][rowID], this->m[2][rowID], this->m[3][rowID] ); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline const Vector4<ElementType> & Matrix4x4<ElementType>::getColumnVector( unsigned int colID ) const
|
||||||
|
{ return this->v[colID]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,32 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "OysterMath.h"
|
||||||
|
|
||||||
|
namespace Oyster { namespace Math
|
||||||
|
{
|
||||||
|
Float2 & operator *= ( Float2 &left, const Float2 &right )
|
||||||
|
{
|
||||||
|
left.x *= right.x;
|
||||||
|
left.y *= right.y;
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
Float3 & operator *= ( Float3 &left, const Float3 &right )
|
||||||
|
{
|
||||||
|
left.x *= right.x;
|
||||||
|
left.y *= right.y;
|
||||||
|
left.z *= right.z;
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
Float4 & operator *= ( Float4 &left, const Float4 &right )
|
||||||
|
{
|
||||||
|
left.x *= right.x;
|
||||||
|
left.y *= right.y;
|
||||||
|
left.z *= right.z;
|
||||||
|
left.w *= right.w;
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
} }
|
|
@ -0,0 +1,220 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef OYSTER_MATH_H
|
||||||
|
#define OYSTER_MATH_H
|
||||||
|
|
||||||
|
#include "Utilities.h"
|
||||||
|
#include "LinearMath.h"
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
namespace Oyster { namespace Math
|
||||||
|
{
|
||||||
|
typedef float Float;
|
||||||
|
|
||||||
|
typedef ::LinearAlgebra::Vector2<Float> Float2;
|
||||||
|
typedef ::LinearAlgebra::Vector3<Float> Float3;
|
||||||
|
typedef ::LinearAlgebra::Vector4<Float> Float4;
|
||||||
|
|
||||||
|
typedef ::LinearAlgebra::Matrix2x2<Float> Float2x2;
|
||||||
|
typedef ::LinearAlgebra::Matrix3x3<Float> Float3x3;
|
||||||
|
typedef ::LinearAlgebra::Matrix4x4<Float> Float4x4;
|
||||||
|
|
||||||
|
typedef Float4x4 Matrix;
|
||||||
|
typedef Float2 Vector2;
|
||||||
|
typedef Float3 Vector3;
|
||||||
|
typedef Float4 Vector4;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Float2 & operator *= ( Float2 &left, const Float2 &right );
|
||||||
|
|
||||||
|
inline Float2 operator * ( const Float2 &left, const Float2 &right )
|
||||||
|
{ return Float2(left) *= right; }
|
||||||
|
|
||||||
|
inline Float2 operator * ( const Float &left, const Float2 &right )
|
||||||
|
{ return Float2(right) *= left; }
|
||||||
|
|
||||||
|
Float3 & operator *= ( Float3 &left, const Float3 &right );
|
||||||
|
|
||||||
|
inline Float3 operator * ( const Float3 &left, const Float3 &right )
|
||||||
|
{ return Float3(left) *= right; }
|
||||||
|
|
||||||
|
inline Float3 operator * ( const Float &left, const Float3 &right )
|
||||||
|
{ return Float3(right) *= left; }
|
||||||
|
|
||||||
|
Float4 & operator *= ( Float4 &left, const Float4 &right );
|
||||||
|
|
||||||
|
inline Float4 operator * ( const Float4 &left, const Float4 &right )
|
||||||
|
{ return Float4(left) *= right; }
|
||||||
|
|
||||||
|
inline Float4 operator * ( const Float &left, const Float4 &right )
|
||||||
|
{ return Float4(right) *= left; }
|
||||||
|
|
||||||
|
inline Float2x2 operator * ( const Float &left, const Float2x2 &right )
|
||||||
|
{ return Float2x2(right) *= left; }
|
||||||
|
|
||||||
|
inline Float3x3 operator * ( const Float &left, const Float3x3 &right )
|
||||||
|
{ return Float3x3(right) *= left; }
|
||||||
|
|
||||||
|
inline Float4x4 operator * ( const Float &left, const Float4x4 &right )
|
||||||
|
{ return Float4x4(right) *= left; }
|
||||||
|
|
||||||
|
// Deprecated function! Use the static const member identity instead.
|
||||||
|
inline void identityMatrix( Float2x2 &output )
|
||||||
|
{ output = Float2x2::identity; }
|
||||||
|
|
||||||
|
// Deprecated function! Use the static const member identity instead.
|
||||||
|
inline void identityMatrix( Float3x3 &output )
|
||||||
|
{ output = Float3x3::identity; }
|
||||||
|
|
||||||
|
// Deprecated function! Use the static const member identity instead.
|
||||||
|
inline void identityMatrix( Float4x4 &output )
|
||||||
|
{ output = Float4x4::identity; }
|
||||||
|
|
||||||
|
// If rigidBody is assumed to be by all definitions a rigid body matrix. Then this is a faster inverse method.
|
||||||
|
inline void inverseRigidBodyMatrix( Float4x4 &output, const Float4x4 &rigidBody )
|
||||||
|
{ ::LinearAlgebra::_3D::inverseRigidBody( output, rigidBody ); }
|
||||||
|
|
||||||
|
inline void translationMatrix( Float4x4 &output, const Float3 &position )
|
||||||
|
{ ::LinearAlgebra::_3D::translationMatrix( output, position ); }
|
||||||
|
|
||||||
|
// counterclockwise rotation around X axis
|
||||||
|
inline void rotationMatrix_AxisX( Float4x4 &output, const Float &radian )
|
||||||
|
{ ::LinearAlgebra::_3D::rotationMatrix_AxisX( output, radian ); }
|
||||||
|
|
||||||
|
// counterclockwise rotation around Y axis
|
||||||
|
inline void rotationMatrix_AxisY( Float4x4 &output, const Float &radian )
|
||||||
|
{ ::LinearAlgebra::_3D::rotationMatrix_AxisY( output, radian ); }
|
||||||
|
|
||||||
|
// counterclockwise rotation around Z axis
|
||||||
|
inline void rotationMatrix_AxisZ( Float4x4 &output, const Float &radian )
|
||||||
|
{ ::LinearAlgebra::_3D::rotationMatrix_AxisZ( output, radian ); }
|
||||||
|
|
||||||
|
// counterclockwise rotation around any given Float3 vector (normalizedAxis). Please make sure it is normalized.
|
||||||
|
inline void rotationMatrix( Float4x4 &output, const Float &radian, const Float3 &normalizedAxis )
|
||||||
|
{ ::LinearAlgebra::_3D::rotationMatrix( output, normalizedAxis, radian ); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
returns a deltaAngularAxis which is a vectorProduct of the particleMovementVector and leverVector.
|
||||||
|
angular: (1/I) * L, there I is known as the "moment of inertia", L as the "angular momentum vector".
|
||||||
|
lever: Displacement vector relative to the center of mass.
|
||||||
|
Recommended reading: http://en.wikipedia.org/wiki/Torque
|
||||||
|
*/
|
||||||
|
inline Float3 deltaAngularAxis( const Float3 &movement, const Float3 &lever )
|
||||||
|
{ return ::LinearAlgebra::_3D::deltaAngularAxis( movement, lever ); }
|
||||||
|
|
||||||
|
inline Float3 particleRotationMovement( const Float3 &deltaRadian, const Float3 &lever )
|
||||||
|
{ return ::LinearAlgebra::_3D::particleRotationMovement( deltaRadian, lever ); }
|
||||||
|
|
||||||
|
inline Float3 vectorProjection( const Float3 &vector, const Float3 &axis )
|
||||||
|
{ return ::LinearAlgebra::_3D::vectorProjection( vector, axis ); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
output: is set to a rigibody matrix that revolve/rotate around centerOfMass and then translates.
|
||||||
|
sumDeltaAngularAxis: sum of all ( (1/I) * ( L x D ) )-vectorproducts. There I is known as "moment of inertia", L as "angular momentum vector" and D the "lever vector".
|
||||||
|
sumTranslation: sum of all the translation vectors.
|
||||||
|
centerOfMass: the point the particles is to revolve around, prior to translation. Default set to null vector aka origo.
|
||||||
|
Recommended reading: http://en.wikipedia.org/wiki/Torque
|
||||||
|
*/
|
||||||
|
inline void rigidBodyMatrix( Float4x4 &output, const Float3 &sumDeltaAngularAxis, const Float3 &sumTranslation, const Float3 ¢erOfMass = Float3::null )
|
||||||
|
{ ::LinearAlgebra::_3D::rigidBodyMatrix( output, sumDeltaAngularAxis, sumTranslation, centerOfMass ); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
output; is set to an orthographic projection matrix.
|
||||||
|
width; of the projection sample volume.
|
||||||
|
height; of the projection sample volume.
|
||||||
|
near: Distance to the nearPlane.
|
||||||
|
far: Distance to the farPlane
|
||||||
|
*/
|
||||||
|
inline void projectionMatrix_Orthographic( Float4x4 &output, const Float &width, const Float &height, const Float &nearClip = ::std::numeric_limits<Float>::epsilon(), const Float &farClip = ::std::numeric_limits<Float>::max() )
|
||||||
|
{ ::LinearAlgebra::_3D::projectionMatrix_Orthographic( output, width, height, nearClip, farClip ); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
output; is set to a perspective transform matrix.
|
||||||
|
vertFoV; is the vertical field of vision in radians. (se FoV Hor+ )
|
||||||
|
aspect; is the screenratio width/height (example 16/9 or 16/10 )
|
||||||
|
near: Distance to the nearPlane
|
||||||
|
far: Distance to the farPlane
|
||||||
|
*/
|
||||||
|
inline void projectionMatrix_Perspective( Float4x4 &output, const Float &verticalFoV, const Float &aspectRatio, const Float &nearClip = ::std::numeric_limits<Float>::epsilon(), const Float &farClip = ::std::numeric_limits<Float>::max() )
|
||||||
|
{ ::LinearAlgebra::_3D::projectionMatrix_Perspective( output, verticalFoV, aspectRatio, nearClip, farClip ); }
|
||||||
|
|
||||||
|
inline Float4x4 & viewProjectionMatrix( Float4x4 &output, const Float4x4 &view, const Float4x4 &projection )
|
||||||
|
{ return output = (view * projection).getTranspose(); }
|
||||||
|
|
||||||
|
inline Float4x4 & transformMatrix( Float4x4 &output, const Float4x4 &transformee, const Float4x4 &transformer )
|
||||||
|
{ return output = transformee * transformer; }
|
||||||
|
|
||||||
|
inline Float4x4 transformMatrix( const Float4x4 &transformee, const Float4x4 &transformer )
|
||||||
|
{ return transformee * transformer; }
|
||||||
|
|
||||||
|
inline Float4 & transformVector( Float4 &output, const Float4 &transformee, const Float4x4 &transformer )
|
||||||
|
{ return output = transformer * transformee; }
|
||||||
|
|
||||||
|
inline Float4 transformVector( const Float4 &transformee, const Float4x4 &transformer )
|
||||||
|
{ return transformee * transformer; }
|
||||||
|
} }
|
||||||
|
|
||||||
|
namespace Utility { namespace Value
|
||||||
|
{ // Utility Value Specializations
|
||||||
|
using namespace ::Oyster::Math;
|
||||||
|
|
||||||
|
template< > inline Float2 abs<Float2>( const Float2 &value )
|
||||||
|
{ return Float2( abs(value.x), abs(value.y) ); }
|
||||||
|
|
||||||
|
template< > inline Float2 max<Float2>( const Float2 &valueA, const Float2 &valueB )
|
||||||
|
{ return Float2( max(valueA.x, valueB.x), max(valueA.y, valueB.y) ); }
|
||||||
|
|
||||||
|
template< > inline Float2 min<Float2>( const Float2 &valueA, const Float2 &valueB )
|
||||||
|
{ return Float2( min(valueA.x, valueB.x), min(valueA.y, valueB.y) ); }
|
||||||
|
|
||||||
|
template< > inline Float3 abs<Float3>( const Float3 &value )
|
||||||
|
{ return Float3( abs(value.xy), abs(value.z) ); }
|
||||||
|
|
||||||
|
template< > inline Float3 max<Float3>( const Float3 &valueA, const Float3 &valueB )
|
||||||
|
{ return Float3( max(valueA.xy, valueB.xy), max(valueA.z, valueB.z) ); }
|
||||||
|
|
||||||
|
template< > inline Float3 min<Float3>( const Float3 &valueA, const Float3 &valueB )
|
||||||
|
{ return Float3( min(valueA.xy, valueB.xy), min(valueA.z, valueB.z) ); }
|
||||||
|
|
||||||
|
template< > inline Float4 abs<Float4>( const Float4 &value )
|
||||||
|
{ return Float4( abs(value.xyz), abs(value.w) ); }
|
||||||
|
|
||||||
|
template< > inline Float4 max<Float4>( const Float4 &valueA, const Float4 &valueB )
|
||||||
|
{ return Float4( max(valueA.xyz, valueB.xyz), max(valueA.w, valueB.w) ); }
|
||||||
|
|
||||||
|
template< > inline Float4 min<Float4>( const Float4 &valueA, const Float4 &valueB )
|
||||||
|
{ return Float4( min(valueA.xyz, valueB.xyz), min(valueA.w, valueB.w) ); }
|
||||||
|
|
||||||
|
template< > inline Float2x2 abs<Float2x2>( const Float2x2 &value )
|
||||||
|
{ return Float2x2( abs(value.v[0]), abs(value.v[1]) ); }
|
||||||
|
|
||||||
|
template< > inline Float2x2 max<Float2x2>( const Float2x2 &valueA, const Float2x2 &valueB )
|
||||||
|
{ return Float2x2( max(valueA.v[0], valueB.v[0]), max(valueA.v[1], valueB.v[1]) ); }
|
||||||
|
|
||||||
|
template< > inline Float2x2 min<Float2x2>( const Float2x2 &valueA, const Float2x2 &valueB )
|
||||||
|
{ return Float2x2( min(valueA.v[0], valueB.v[0]), min(valueA.v[1], valueB.v[1]) ); }
|
||||||
|
|
||||||
|
template< > inline Float3x3 abs<Float3x3>( const Float3x3 &value )
|
||||||
|
{ return Float3x3( abs(value.v[0]), abs(value.v[1]), abs(value[2]) ); }
|
||||||
|
|
||||||
|
template< > inline Float3x3 max<Float3x3>( const Float3x3 &valueA, const Float3x3 &valueB )
|
||||||
|
{ return Float3x3( max(valueA.v[0], valueB.v[0]), max(valueA.v[1], valueB.v[1]), max(valueA.v[2], valueB.v[2]) ); }
|
||||||
|
|
||||||
|
template< > inline Float3x3 min<Float3x3>( const Float3x3 &valueA, const Float3x3 &valueB )
|
||||||
|
{ return Float3x3( min(valueA.v[0], valueB.v[0]), min(valueA.v[1], valueB.v[1]), min(valueA.v[2], valueB.v[2]) ); }
|
||||||
|
|
||||||
|
template< > inline Float4x4 abs<Float4x4>( const Float4x4 &value )
|
||||||
|
{ return Float4x4( abs(value.v[0]), abs(value.v[1]), abs(value[2]), abs(value[3]) ); }
|
||||||
|
|
||||||
|
template< > inline Float4x4 max<Float4x4>( const Float4x4 &valueA, const Float4x4 &valueB )
|
||||||
|
{ return Float4x4( max(valueA.v[0], valueB.v[0]), max(valueA.v[1], valueB.v[1]), max(valueA.v[2], valueB.v[2]), max(valueA.v[3], valueB.v[3]) ); }
|
||||||
|
|
||||||
|
template< > inline Float4x4 min<Float4x4>( const Float4x4 &valueA, const Float4x4 &valueB )
|
||||||
|
{ return Float4x4( min(valueA.v[0], valueB.v[0]), min(valueA.v[1], valueB.v[1]), min(valueA.v[2], valueB.v[2]), min(valueA.v[3], valueB.v[3]) ); }
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,183 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Linear Math Quaternions
|
||||||
|
// © Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef LINEARALGEBRA_QUATERNION_H
|
||||||
|
#define LINEARALGEBRA_QUATERNION_H
|
||||||
|
|
||||||
|
#include "Vector.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
namespace LinearAlgebra
|
||||||
|
{
|
||||||
|
template<typename ElementType>
|
||||||
|
class Quaternion
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct{ Vector3<ElementType> imaginary; ElementType real; };
|
||||||
|
ElementType element[4];
|
||||||
|
char byte[sizeof(ElementType[2])];
|
||||||
|
};
|
||||||
|
|
||||||
|
Quaternion( );
|
||||||
|
Quaternion( const Quaternion &quaternion );
|
||||||
|
Quaternion( const Vector3<ElementType> &imaginary, const ElementType &real );
|
||||||
|
~Quaternion( );
|
||||||
|
|
||||||
|
operator ElementType* ( );
|
||||||
|
operator const ElementType* ( ) const;
|
||||||
|
operator char* ( );
|
||||||
|
operator const char* ( ) const;
|
||||||
|
ElementType & operator [] ( int i );
|
||||||
|
const ElementType & operator [] ( int i ) const;
|
||||||
|
|
||||||
|
Quaternion<ElementType> & operator = ( const Quaternion<ElementType> &quaternion );
|
||||||
|
Quaternion<ElementType> & operator *= ( const ElementType &scalar );
|
||||||
|
Quaternion<ElementType> & operator /= ( const ElementType &scalar );
|
||||||
|
Quaternion<ElementType> & operator += ( const Quaternion<ElementType> &quaternion );
|
||||||
|
Quaternion<ElementType> & operator -= ( const Quaternion<ElementType> &quaternion );
|
||||||
|
Quaternion<ElementType> operator * ( const Quaternion<ElementType> &quaternion ) const;
|
||||||
|
Quaternion<ElementType> operator * ( const Vector3<ElementType> &vector ) const;
|
||||||
|
Quaternion<ElementType> operator * ( const ElementType &scalar ) const;
|
||||||
|
Quaternion<ElementType> operator / ( const ElementType &scalar ) const;
|
||||||
|
Quaternion<ElementType> operator + ( const Quaternion<ElementType> &quaternion ) const;
|
||||||
|
Quaternion<ElementType> operator - ( const Quaternion<ElementType> &quaternion ) const;
|
||||||
|
Quaternion<ElementType> operator - ( ) const;
|
||||||
|
|
||||||
|
Quaternion<ElementType> getConjugate( ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Body
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Quaternion<ElementType>::Quaternion( ) : imaginary(0,0,0), real(0) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Quaternion<ElementType>::Quaternion( const Quaternion &quaternion ) : imaginary(quaternion.imaginary), real(quaternion.real) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Quaternion<ElementType>::Quaternion( const Vector3<ElementType> &_imaginary, const ElementType &_real ) : imaginary(_imaginary), real(_real) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Quaternion<ElementType>::~Quaternion( ) { /* Nothing that needs to be done */ }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Quaternion<ElementType>::operator ElementType* ( )
|
||||||
|
{ return this->element; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Quaternion<ElementType>::operator const ElementType* ( ) const
|
||||||
|
{ return this->element; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Quaternion<ElementType>::operator char* ( )
|
||||||
|
{ return this->byte; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Quaternion<ElementType>::operator const char* ( ) const
|
||||||
|
{ return this->byte; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline ElementType & Quaternion<ElementType>::operator [] ( int i )
|
||||||
|
{ return this->element[i]; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline const ElementType & Quaternion<ElementType>::operator [] ( int i ) const
|
||||||
|
{ return this->element[i]; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Quaternion<ElementType> & Quaternion<ElementType>::operator = ( const Quaternion<ElementType> &quaternion )
|
||||||
|
{
|
||||||
|
this->imaginary = quaternion.imaginary;
|
||||||
|
this->real = quaternion.real;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Quaternion<ElementType> & Quaternion<ElementType>::operator *= ( const ElementType &scalar )
|
||||||
|
{
|
||||||
|
this->imaginary *= scalar;
|
||||||
|
this->real *= scalar;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Quaternion<ElementType> & Quaternion<ElementType>::operator /= ( const ElementType &scalar )
|
||||||
|
{
|
||||||
|
this->imaginary /= scalar;
|
||||||
|
this->real /= scalar;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Quaternion<ElementType> & Quaternion<ElementType>::operator += ( const Quaternion<ElementType> &quaternion )
|
||||||
|
{
|
||||||
|
this->imaginary += quaternion.imaginary;
|
||||||
|
this->real += quaternion.real;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Quaternion<ElementType> & Quaternion<ElementType>::operator -= ( const Quaternion<ElementType> &quaternion )
|
||||||
|
{
|
||||||
|
this->imaginary -= quaternion.imaginary;
|
||||||
|
this->real -= quaternion.real;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Quaternion<ElementType> Quaternion<ElementType>::operator * ( const Quaternion<ElementType> &quaternion ) const
|
||||||
|
{
|
||||||
|
Vector3<ElementType> im = this->imaginary.cross( quaternion.imaginary );
|
||||||
|
im += (quaternion.imaginary * this->real);
|
||||||
|
im += (this->imaginary * quaternion.real);
|
||||||
|
|
||||||
|
ElementType re = this->real * quaternion.real;
|
||||||
|
re -= this->imaginary.dot( quaternion.imaginary );
|
||||||
|
|
||||||
|
return Quaternion<ElementType>( im, re );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Quaternion<ElementType> Quaternion<ElementType>::operator * ( const Vector3<ElementType> &vector ) const
|
||||||
|
{
|
||||||
|
Vector3<ElementType> im = this->imaginary.cross( vector );
|
||||||
|
im += (vector * this->real);
|
||||||
|
|
||||||
|
ElementType re = this->imaginary.dot( vector ) * -1;
|
||||||
|
|
||||||
|
return Quaternion<ElementType>( im, re );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Quaternion<ElementType> Quaternion<ElementType>::operator * ( const ElementType &scalar ) const
|
||||||
|
{ return Quaternion<ElementType>(*this) *= scalar; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Quaternion<ElementType> Quaternion<ElementType>::operator / ( const ElementType &scalar ) const
|
||||||
|
{ return Quaternion<ElementType>(*this) /= scalar; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Quaternion<ElementType> Quaternion<ElementType>::operator + ( const Quaternion<ElementType> &quaternion ) const
|
||||||
|
{ return Quaternion<ElementType>(*this) += quaternion; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Quaternion<ElementType> Quaternion<ElementType>::operator - ( const Quaternion<ElementType> &quaternion ) const
|
||||||
|
{ return Quaternion<ElementType>(*this) -= quaternion; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Quaternion<ElementType> Quaternion<ElementType>::operator - ( ) const
|
||||||
|
{ return Quaternion<ElementType>(-this->imaginary, -this->real); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Quaternion<ElementType> Quaternion<ElementType>::getConjugate( ) const
|
||||||
|
{ return Quaternion<ElementType>(this->imaginary * -1, this->real ); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,659 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Linear Math Vectors
|
||||||
|
// © Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef LINEARALGEBRA_VECTOR_H
|
||||||
|
#define LINEARALGEBRA_VECTOR_H
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
namespace LinearAlgebra
|
||||||
|
{
|
||||||
|
template<typename ElementType>
|
||||||
|
class Vector2
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct { ElementType x, y; };
|
||||||
|
ElementType element[2];
|
||||||
|
char byte[sizeof(ElementType[2])];
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Vector2<ElementType> null;
|
||||||
|
static const Vector2<ElementType> standardUnitX;
|
||||||
|
static const Vector2<ElementType> standardUnitY;
|
||||||
|
|
||||||
|
Vector2( );
|
||||||
|
Vector2( const Vector2<ElementType> &vector );
|
||||||
|
Vector2( const ElementType &element );
|
||||||
|
Vector2( const ElementType element[2] );
|
||||||
|
Vector2( const ElementType &x, const ElementType &y );
|
||||||
|
~Vector2( );
|
||||||
|
|
||||||
|
operator ElementType* ( );
|
||||||
|
operator const ElementType* ( ) const;
|
||||||
|
operator char* ( );
|
||||||
|
operator const char* ( ) const;
|
||||||
|
ElementType & operator [] ( int i );
|
||||||
|
const ElementType & operator [] ( int i ) const;
|
||||||
|
|
||||||
|
Vector2<ElementType> & operator = ( const Vector2<ElementType> &vector );
|
||||||
|
Vector2<ElementType> & operator = ( const ElementType element[2] );
|
||||||
|
Vector2<ElementType> & operator *= ( const ElementType &scalar );
|
||||||
|
Vector2<ElementType> & operator /= ( const ElementType &scalar );
|
||||||
|
Vector2<ElementType> & operator += ( const Vector2<ElementType> &vector );
|
||||||
|
Vector2<ElementType> & operator -= ( const Vector2<ElementType> &vector );
|
||||||
|
Vector2<ElementType> operator * ( const ElementType &scalar ) const;
|
||||||
|
Vector2<ElementType> operator / ( const ElementType &scalar ) const;
|
||||||
|
Vector2<ElementType> operator + ( const Vector2<ElementType> &vector ) const;
|
||||||
|
Vector2<ElementType> operator - ( const Vector2<ElementType> &vector ) const;
|
||||||
|
Vector2<ElementType> operator - ( ) const; // unary negation
|
||||||
|
|
||||||
|
bool operator == ( const Vector2<ElementType> &vector ) const;
|
||||||
|
bool operator != ( const Vector2<ElementType> &vector ) const;
|
||||||
|
|
||||||
|
ElementType length( ) const;
|
||||||
|
ElementType dot( const Vector2<ElementType> &vector ) const;
|
||||||
|
|
||||||
|
Vector2<ElementType> & normalize( );
|
||||||
|
Vector2<ElementType> getNormalized( ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
class Vector3
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct { ElementType x, y, z; };
|
||||||
|
struct { Vector2<ElementType> xy; };
|
||||||
|
ElementType element[3];
|
||||||
|
char byte[sizeof(ElementType[3])];
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Vector3<ElementType> null;
|
||||||
|
static const Vector3<ElementType> standardUnitX;
|
||||||
|
static const Vector3<ElementType> standardUnitY;
|
||||||
|
static const Vector3<ElementType> standardUnitZ;
|
||||||
|
|
||||||
|
Vector3( );
|
||||||
|
Vector3( const Vector3<ElementType> &vector );
|
||||||
|
Vector3( const Vector2<ElementType> &vector, const ElementType &z );
|
||||||
|
Vector3( const ElementType &element );
|
||||||
|
Vector3( const ElementType element[3] );
|
||||||
|
Vector3( const ElementType &x, const ElementType &y, const ElementType &z );
|
||||||
|
~Vector3( );
|
||||||
|
|
||||||
|
operator ElementType* ();
|
||||||
|
operator const ElementType* () const;
|
||||||
|
operator char* ( );
|
||||||
|
operator const char* ( ) const;
|
||||||
|
ElementType & operator [] ( int i );
|
||||||
|
const ElementType & operator [] ( int i ) const;
|
||||||
|
|
||||||
|
Vector3<ElementType> & operator = ( const Vector3<ElementType> &vector );
|
||||||
|
Vector3<ElementType> & operator = ( const ElementType element[3] );
|
||||||
|
Vector3<ElementType> & operator *= ( const ElementType &scalar );
|
||||||
|
Vector3<ElementType> & operator /= ( const ElementType &scalar );
|
||||||
|
Vector3<ElementType> & operator += ( const Vector3<ElementType> &vector );
|
||||||
|
Vector3<ElementType> & operator -= ( const Vector3<ElementType> &vector );
|
||||||
|
Vector3<ElementType> operator * ( const ElementType &scalar ) const;
|
||||||
|
Vector3<ElementType> operator / ( const ElementType &scalar ) const;
|
||||||
|
Vector3<ElementType> operator + ( const Vector3<ElementType> &vector ) const;
|
||||||
|
Vector3<ElementType> operator - ( const Vector3<ElementType> &vector ) const;
|
||||||
|
Vector3<ElementType> operator - ( ) const; // unary negation
|
||||||
|
|
||||||
|
bool operator == ( const Vector3<ElementType> &vector ) const;
|
||||||
|
bool operator != ( const Vector3<ElementType> &vector ) const;
|
||||||
|
|
||||||
|
ElementType length( ) const;
|
||||||
|
ElementType dot( const Vector3<ElementType> &vector ) const;
|
||||||
|
Vector3<ElementType> cross( const Vector3<ElementType> &vector ) const;
|
||||||
|
|
||||||
|
Vector3<ElementType> & normalize( );
|
||||||
|
Vector3<ElementType> getNormalized( ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
class Vector4
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct { ElementType x, y, z, w; };
|
||||||
|
struct { Vector2<ElementType> xy; };
|
||||||
|
struct { Vector3<ElementType> xyz; };
|
||||||
|
ElementType element[4];
|
||||||
|
char byte[sizeof(ElementType[4])];
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Vector4<ElementType> null;
|
||||||
|
static const Vector4<ElementType> standardUnitX;
|
||||||
|
static const Vector4<ElementType> standardUnitY;
|
||||||
|
static const Vector4<ElementType> standardUnitZ;
|
||||||
|
static const Vector4<ElementType> standardUnitW;
|
||||||
|
|
||||||
|
Vector4( );
|
||||||
|
Vector4( const Vector4<ElementType> &vector );
|
||||||
|
Vector4( const Vector3<ElementType> &vector, const ElementType &w );
|
||||||
|
Vector4( const Vector2<ElementType> &vector, const ElementType &z, const ElementType &w );
|
||||||
|
Vector4( const ElementType &element );
|
||||||
|
Vector4( const ElementType element[4] );
|
||||||
|
Vector4( const ElementType &x, const ElementType &y, const ElementType &z, const ElementType &w );
|
||||||
|
~Vector4( );
|
||||||
|
|
||||||
|
operator ElementType* ();
|
||||||
|
operator const ElementType* () const;
|
||||||
|
operator char* ( );
|
||||||
|
operator const char* ( ) const;
|
||||||
|
ElementType & operator [] ( int i );
|
||||||
|
const ElementType & operator [] ( int i ) const;
|
||||||
|
|
||||||
|
Vector4<ElementType> & operator = ( const Vector4<ElementType> &vector );
|
||||||
|
Vector4<ElementType> & operator = ( const ElementType element[4] );
|
||||||
|
Vector4<ElementType> & operator *= ( const ElementType &scalar );
|
||||||
|
Vector4<ElementType> & operator /= ( const ElementType &scalar );
|
||||||
|
Vector4<ElementType> & operator += ( const Vector4<ElementType> &vector );
|
||||||
|
Vector4<ElementType> & operator -= ( const Vector4<ElementType> &vector );
|
||||||
|
Vector4<ElementType> operator * ( const ElementType &scalar ) const;
|
||||||
|
Vector4<ElementType> operator / ( const ElementType &scalar ) const;
|
||||||
|
Vector4<ElementType> operator + ( const Vector4<ElementType> &vector ) const;
|
||||||
|
Vector4<ElementType> operator - ( const Vector4<ElementType> &vector ) const;
|
||||||
|
Vector4<ElementType> operator - ( ) const; // unary negation
|
||||||
|
|
||||||
|
bool operator == ( const Vector4<ElementType> &vector ) const;
|
||||||
|
bool operator != ( const Vector4<ElementType> &vector ) const;
|
||||||
|
|
||||||
|
ElementType length( ) const;
|
||||||
|
ElementType dot( const Vector4<ElementType> &vector ) const;
|
||||||
|
|
||||||
|
Vector4<ElementType> & normalize( );
|
||||||
|
Vector4<ElementType> getNormalized( ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Body
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Vector2<ElementType> ///////////////////////////////////////
|
||||||
|
template<typename ElementType> const Vector2<ElementType> Vector2<ElementType>::null = Vector2<ElementType>( );
|
||||||
|
template<typename ElementType> const Vector2<ElementType> Vector2<ElementType>::standardUnitX = Vector2<ElementType>( 1, 0 );
|
||||||
|
template<typename ElementType> const Vector2<ElementType> Vector2<ElementType>::standardUnitY = Vector2<ElementType>( 0, 1 );
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector2<ElementType>::Vector2( ) : x(0), y(0) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector2<ElementType>::Vector2( const Vector2<ElementType> &vector ) : x(vector.x), y(vector.y)
|
||||||
|
{ this->x = vector.x; this->y = vector.y; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector2<ElementType>::Vector2( const ElementType &_element ) : x(_element), y(_element)
|
||||||
|
{ this->x = this->y = _element; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector2<ElementType>::Vector2( const ElementType _element[2] ) : x(_element[0]), y(_element[1]) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector2<ElementType>::Vector2( const ElementType &_x, const ElementType &_y ) : x(_x), y(_y) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector2<ElementType>::~Vector2( ) { /* Nothing that needs to be done */ }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector2<ElementType>::operator ElementType* ()
|
||||||
|
{ return this->element; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector2<ElementType>::operator const ElementType* () const
|
||||||
|
{ return this->element; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector2<ElementType>::operator char* ( )
|
||||||
|
{ return this->byte; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector2<ElementType>::operator const char* ( ) const
|
||||||
|
{ return this->byte; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline ElementType & Vector2<ElementType>::operator [] ( int i )
|
||||||
|
{ return this->element[i]; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline const ElementType & Vector2<ElementType>::operator [] ( int i ) const
|
||||||
|
{ return this->element[i]; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector2<ElementType> & Vector2<ElementType>::operator = ( const Vector2<ElementType> &vector )
|
||||||
|
{
|
||||||
|
this->element[0] = vector.element[0];
|
||||||
|
this->element[1] = vector.element[1];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector2<ElementType> & Vector2<ElementType>::operator = ( const ElementType _element[2] )
|
||||||
|
{
|
||||||
|
this->element[0] = _element[0];
|
||||||
|
this->element[1] = _element[1];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector2<ElementType> & Vector2<ElementType>::operator *= ( const ElementType &scalar )
|
||||||
|
{
|
||||||
|
this->element[0] *= scalar;
|
||||||
|
this->element[1] *= scalar;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector2<ElementType> & Vector2<ElementType>::operator /= ( const ElementType &scalar )
|
||||||
|
{
|
||||||
|
this->element[0] /= scalar;
|
||||||
|
this->element[1] /= scalar;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector2<ElementType> & Vector2<ElementType>::operator += ( const Vector2<ElementType> &vector )
|
||||||
|
{
|
||||||
|
this->element[0] += vector.element[0];
|
||||||
|
this->element[1] += vector.element[1];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector2<ElementType> & Vector2<ElementType>::operator -= ( const Vector2<ElementType> &vector )
|
||||||
|
{
|
||||||
|
this->element[0] -= vector.element[0];
|
||||||
|
this->element[1] -= vector.element[1];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector2<ElementType> Vector2<ElementType>::operator * ( const ElementType &scalar ) const
|
||||||
|
{ return Vector2<ElementType>(*this) *= scalar; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector2<ElementType> Vector2<ElementType>::operator / ( const ElementType &scalar ) const
|
||||||
|
{ return Vector2<ElementType>(*this) /= scalar; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector2<ElementType> Vector2<ElementType>::operator + ( const Vector2<ElementType> &vector ) const
|
||||||
|
{ return Vector2<ElementType>(*this) += vector; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector2<ElementType> Vector2<ElementType>::operator - ( const Vector2<ElementType> &vector ) const
|
||||||
|
{ return Vector2<ElementType>(*this) -= vector; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector2<ElementType> Vector2<ElementType>::operator - ( ) const
|
||||||
|
{ return Vector2<ElementType>(-this->x, -this->y); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
bool Vector2<ElementType>::operator == ( const Vector2<ElementType> &vector ) const
|
||||||
|
{
|
||||||
|
if( this->x != vector.x ) return false;
|
||||||
|
if( this->y != vector.y ) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
bool Vector2<ElementType>::operator != ( const Vector2<ElementType> &vector ) const
|
||||||
|
{
|
||||||
|
if( this->x != vector.x ) return true;
|
||||||
|
if( this->y != vector.y ) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline ElementType Vector2<ElementType>::length( ) const
|
||||||
|
{ return (ElementType) ::sqrt( this->dot(*this) ); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
ElementType Vector2<ElementType>::dot( const Vector2<ElementType> &vector ) const
|
||||||
|
{
|
||||||
|
ElementType value = 0;
|
||||||
|
value += this->element[0] * vector.element[0];
|
||||||
|
value += this->element[1] * vector.element[1];
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector2<ElementType> & Vector2<ElementType>::normalize( )
|
||||||
|
{ return (*this) /= this->length(); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector2<ElementType> Vector2<ElementType>::getNormalized( ) const
|
||||||
|
{ return Vector2<ElementType>(*this).normalize(); }
|
||||||
|
|
||||||
|
// Vector3<ElementType> ///////////////////////////////////////
|
||||||
|
template<typename ElementType> const Vector3<ElementType> Vector3<ElementType>::null = Vector3<ElementType>( );
|
||||||
|
template<typename ElementType> const Vector3<ElementType> Vector3<ElementType>::standardUnitX = Vector3<ElementType>( 1, 0, 0 );
|
||||||
|
template<typename ElementType> const Vector3<ElementType> Vector3<ElementType>::standardUnitY = Vector3<ElementType>( 0, 1, 0 );
|
||||||
|
template<typename ElementType> const Vector3<ElementType> Vector3<ElementType>::standardUnitZ = Vector3<ElementType>( 0, 0, 1 );
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector3<ElementType>::Vector3( ) : x(0), y(0), z(0) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector3<ElementType>::Vector3( const Vector3<ElementType> &vector ) : x(vector.x), y(vector.y), z(vector.z)
|
||||||
|
{ this->x = vector.x; this->y = vector.y; this->z = vector.z; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector3<ElementType>::Vector3( const Vector2<ElementType> &vector, const ElementType &_z ) : x(vector.x), y(vector.y), z(_z)
|
||||||
|
{ this->x = vector.x; this->y = vector.y; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector3<ElementType>::Vector3( const ElementType &_element ) : x(_element), y(_element), z(_element)
|
||||||
|
{ this->x = this->y = this->z = _element; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector3<ElementType>::Vector3( const ElementType _element[3] ) : x(_element[0]), y(_element[1]), z(_element[2]) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector3<ElementType>::Vector3( const ElementType &_x, const ElementType &_y, const ElementType &_z ) : x(_x), y(_y), z(_z)
|
||||||
|
{ this->x = _x; this->y = _y; this->z = _z; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector3<ElementType>::~Vector3( ) { /* Nothing that needs to be done */ }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector3<ElementType>::operator ElementType* ()
|
||||||
|
{ return this->element; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector3<ElementType>::operator const ElementType* () const
|
||||||
|
{ return this->element; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline ElementType & Vector3<ElementType>::operator [] ( int i )
|
||||||
|
{ return this->element[i]; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline const ElementType & Vector3<ElementType>::operator [] ( int i ) const
|
||||||
|
{ return this->element[i]; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector3<ElementType> & Vector3<ElementType>::operator = ( const Vector3<ElementType> &vector )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 3; ++i )
|
||||||
|
this->element[i] = vector.element[i];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector3<ElementType> & Vector3<ElementType>::operator = ( const ElementType element[3] )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 3; ++i )
|
||||||
|
this->element[i] = element[i];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector3<ElementType> & Vector3<ElementType>::operator *= ( const ElementType &scalar )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 3; ++i )
|
||||||
|
this->element[i] *= scalar;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector3<ElementType> & Vector3<ElementType>::operator /= ( const ElementType &scalar )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 3; ++i )
|
||||||
|
this->element[i] /= scalar;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector3<ElementType> & Vector3<ElementType>::operator += ( const Vector3<ElementType> &vector )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 3; ++i )
|
||||||
|
this->element[i] += vector.element[i];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector3<ElementType> & Vector3<ElementType>::operator -= ( const Vector3<ElementType> &vector )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 3; ++i )
|
||||||
|
this->element[i] -= vector.element[i];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector3<ElementType> Vector3<ElementType>::operator * ( const ElementType &scalar ) const
|
||||||
|
{ return Vector3<ElementType>(*this) *= scalar; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector3<ElementType> Vector3<ElementType>::operator / ( const ElementType &scalar ) const
|
||||||
|
{ return Vector3<ElementType>(*this) /= scalar; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector3<ElementType> Vector3<ElementType>::operator + ( const Vector3<ElementType> &vector ) const
|
||||||
|
{ return Vector3<ElementType>(*this) += vector; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector3<ElementType> Vector3<ElementType>::operator - ( const Vector3<ElementType> &vector ) const
|
||||||
|
{ return Vector3<ElementType>(*this) -= vector; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector3<ElementType> Vector3<ElementType>::operator - ( ) const
|
||||||
|
{ return Vector3<ElementType>(-this->x, -this->y, -this->z); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
bool Vector3<ElementType>::operator == ( const Vector3<ElementType> &vector ) const
|
||||||
|
{
|
||||||
|
if( this->x != vector.x ) return false;
|
||||||
|
if( this->y != vector.y ) return false;
|
||||||
|
if( this->z != vector.z ) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
bool Vector3<ElementType>::operator != ( const Vector3<ElementType> &vector ) const
|
||||||
|
{
|
||||||
|
if( this->x != vector.x ) return true;
|
||||||
|
if( this->y != vector.y ) return true;
|
||||||
|
if( this->z != vector.z ) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline ElementType Vector3<ElementType>::length( ) const
|
||||||
|
{ return (ElementType) ::sqrt( this->dot(*this) ); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
ElementType Vector3<ElementType>::dot( const Vector3<ElementType> &vector ) const
|
||||||
|
{
|
||||||
|
ElementType value = 0;
|
||||||
|
for( int i = 0; i < 3; ++i )
|
||||||
|
value += this->element[i] * vector.element[i];
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector3<ElementType> Vector3<ElementType>::cross( const Vector3<ElementType> &vector ) const
|
||||||
|
{
|
||||||
|
return Vector3<ElementType>( (this->y*vector.z) - (this->z*vector.y),
|
||||||
|
(this->z*vector.x) - (this->x*vector.z),
|
||||||
|
(this->x*vector.y) - (this->y*vector.x) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector3<ElementType> & Vector3<ElementType>::normalize( )
|
||||||
|
{ return (*this) /= this->length(); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector3<ElementType> Vector3<ElementType>::getNormalized( ) const
|
||||||
|
{ return Vector3<ElementType>(*this).normalize(); }
|
||||||
|
|
||||||
|
// Vector4<ElementType> ///////////////////////////////////////
|
||||||
|
template<typename ElementType> const Vector4<ElementType> Vector4<ElementType>::null = Vector4<ElementType>( );
|
||||||
|
template<typename ElementType> const Vector4<ElementType> Vector4<ElementType>::standardUnitX = Vector4<ElementType>( 1, 0, 0, 0 );
|
||||||
|
template<typename ElementType> const Vector4<ElementType> Vector4<ElementType>::standardUnitY = Vector4<ElementType>( 0, 1, 0, 0 );
|
||||||
|
template<typename ElementType> const Vector4<ElementType> Vector4<ElementType>::standardUnitZ = Vector4<ElementType>( 0, 0, 1, 0 );
|
||||||
|
template<typename ElementType> const Vector4<ElementType> Vector4<ElementType>::standardUnitW = Vector4<ElementType>( 0, 0, 0, 1 );
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector4<ElementType>::Vector4( ) : x(0), y(0), z(0), w(0) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector4<ElementType>::Vector4( const Vector4<ElementType> &vector ) : x(vector.x), y(vector.y), z(vector.z), w(vector.z)
|
||||||
|
{ this->x = vector.x; this->y = vector.y; this->z = vector.z; this->w = vector.w; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector4<ElementType>::Vector4( const Vector3<ElementType> &vector, const ElementType &_w ) : x(vector.x), y(vector.y), z(vector.z), w(_w)
|
||||||
|
{ this->x = vector.x; this->y = vector.y; this->z = vector.z; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector4<ElementType>::Vector4( const Vector2<ElementType> &vector, const ElementType &_z, const ElementType &_w ) : x(vector.x), y(vector.y), z(_z), w(_w)
|
||||||
|
{ this->x = vector.x; this->y = vector.y; this->z = _z; this->w = _w; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector4<ElementType>::Vector4( const ElementType &_element ) : x(_element), y(_element), z(_element), w(_element)
|
||||||
|
{ this->x = this->y = this->z = this->w = _element; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector4<ElementType>::Vector4( const ElementType _element[4] ) : x(_element[0]), y(_element[1]), z(_element[2]), w(_element[3]) {}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector4<ElementType>::Vector4( const ElementType &_x, const ElementType &_y, const ElementType &_z, const ElementType &_w ) : x(_x), y(_y), z(_z), w(_w)
|
||||||
|
{ this->x = _x; this->y = _y; this->z = _z; this->w = _w; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector4<ElementType>::~Vector4( ) { /* Nothing that needs to be done */ }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector4<ElementType>::operator ElementType* ()
|
||||||
|
{ return this->element; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector4<ElementType>::operator const ElementType* () const
|
||||||
|
{ return this->element; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline ElementType & Vector4<ElementType>::operator [] ( int i )
|
||||||
|
{ return this->element[i]; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline const ElementType & Vector4<ElementType>::operator [] ( int i ) const
|
||||||
|
{ return this->element[i]; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector4<ElementType> & Vector4<ElementType>::operator = ( const Vector4<ElementType> &vector )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 4; ++i )
|
||||||
|
this->element[i] = vector.element[i];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector4<ElementType> & Vector4<ElementType>::operator = ( const ElementType element[4] )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 4; ++i )
|
||||||
|
this->element[i] = element[i];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector4<ElementType> & Vector4<ElementType>::operator *= ( const ElementType &scalar )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 4; ++i )
|
||||||
|
this->element[i] *= scalar;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector4<ElementType> & Vector4<ElementType>::operator /= ( const ElementType &scalar )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 4; ++i )
|
||||||
|
this->element[i] /= scalar;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector4<ElementType> & Vector4<ElementType>::operator += ( const Vector4<ElementType> &vector )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 4; ++i )
|
||||||
|
this->element[i] += vector.element[i];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
Vector4<ElementType> & Vector4<ElementType>::operator -= ( const Vector4<ElementType> &vector )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 4; ++i )
|
||||||
|
this->element[i] -= vector.element[i];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector4<ElementType> Vector4<ElementType>::operator * ( const ElementType &scalar ) const
|
||||||
|
{ return Vector4<ElementType>(*this) *= scalar; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector4<ElementType> Vector4<ElementType>::operator / ( const ElementType &scalar ) const
|
||||||
|
{ return Vector4<ElementType>(*this) /= scalar; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector4<ElementType> Vector4<ElementType>::operator + ( const Vector4<ElementType> &vector ) const
|
||||||
|
{ return Vector4<ElementType>(*this) += vector; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector4<ElementType> Vector4<ElementType>::operator - ( const Vector4<ElementType> &vector ) const
|
||||||
|
{ return Vector4<ElementType>(*this) -= vector; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector4<ElementType> Vector4<ElementType>::operator - ( ) const
|
||||||
|
{ return Vector4<ElementType>(-this->x, -this->y, -this->z, -this->w); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
bool Vector4<ElementType>::operator == ( const Vector4<ElementType> &vector ) const
|
||||||
|
{
|
||||||
|
if( this->x != vector.x ) return false;
|
||||||
|
if( this->y != vector.y ) return false;
|
||||||
|
if( this->z != vector.z ) return false;
|
||||||
|
if( this->w != vector.w ) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
bool Vector4<ElementType>::operator != ( const Vector4<ElementType> &vector ) const
|
||||||
|
{
|
||||||
|
if( this->x != vector.x ) return true;
|
||||||
|
if( this->y != vector.y ) return true;
|
||||||
|
if( this->z != vector.z ) return true;
|
||||||
|
if( this->w != vector.w ) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline ElementType Vector4<ElementType>::length( ) const
|
||||||
|
{ return (ElementType) ::sqrt( this->dot(*this) ); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
ElementType Vector4<ElementType>::dot( const Vector4<ElementType> &vector ) const
|
||||||
|
{
|
||||||
|
ElementType value = 0;
|
||||||
|
for( int i = 0; i < 4; ++i )
|
||||||
|
value += this->element[i] * vector.element[i];
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector4<ElementType> & Vector4<ElementType>::normalize( )
|
||||||
|
{ return (*this) /= this->length(); }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline Vector4<ElementType> Vector4<ElementType>::getNormalized( ) const
|
||||||
|
{ return Vector4<ElementType>(*this).normalize(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,216 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Utility Collection of Miscellanious Handy Functions
|
||||||
|
// © Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "Utilities.h"
|
||||||
|
#include <sstream>
|
||||||
|
#include <locale>
|
||||||
|
|
||||||
|
using ::std::vector;
|
||||||
|
using ::std::string;
|
||||||
|
|
||||||
|
namespace Utility
|
||||||
|
{
|
||||||
|
// PRIVATE STATIC ////////////////////////////////////////////////////
|
||||||
|
namespace PrivateStatic
|
||||||
|
{
|
||||||
|
const ::std::locale systemDefaultLocale = ::std::locale();
|
||||||
|
}
|
||||||
|
|
||||||
|
// STRING ////////////////////////////////////////////////////////////
|
||||||
|
namespace String
|
||||||
|
{
|
||||||
|
vector<string> & split( vector<string> &output, const string &str, char delim, string::size_type offset )
|
||||||
|
{
|
||||||
|
if( str.length() > 0 )
|
||||||
|
{
|
||||||
|
while( offset < str.length() ) // trim
|
||||||
|
{
|
||||||
|
if( str[offset] == delim )
|
||||||
|
++offset;
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
|
||||||
|
string::size_type delimPos = str.find_first_of( delim, offset );
|
||||||
|
if( delimPos == string::npos )
|
||||||
|
{
|
||||||
|
if( str.length() > offset )
|
||||||
|
output.push_back( str.substr( offset, str.length() - offset ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( delimPos > offset )
|
||||||
|
output.push_back( str.substr( offset, delimPos - offset ) );
|
||||||
|
String::split( output, str, delim, delimPos + 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<string> & split( vector<string> &output, const string &str, const string &delim, string::size_type offset )
|
||||||
|
{
|
||||||
|
if( str.length() > 0 )
|
||||||
|
{
|
||||||
|
string::size_type delimPos = str.find_first_of( delim, offset );
|
||||||
|
if( delimPos == string::npos )
|
||||||
|
{
|
||||||
|
if( str.length() > offset )
|
||||||
|
output.push_back( str.substr( offset, str.length() - offset ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( delimPos > offset )
|
||||||
|
output.push_back( str.substr( offset, delimPos - offset ) );
|
||||||
|
String::split( output, str, delim, delimPos + delim.length() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<string> & split( vector<string> &output, const string &str, const vector<string> &delim, string::size_type offset )
|
||||||
|
{
|
||||||
|
if( str.length() > 0 )
|
||||||
|
{
|
||||||
|
string::size_type firstDelimPos = str.length(), delimPos;
|
||||||
|
|
||||||
|
vector<string>::size_type numDelims = delim.size(), delimRef = 0;
|
||||||
|
for( vector<string>::size_type i = 0; i < numDelims ; ++i )
|
||||||
|
{
|
||||||
|
delimPos = str.find_first_of( delim[i], offset );
|
||||||
|
if( delimPos != string::npos ) if( delimPos < firstDelimPos )
|
||||||
|
{
|
||||||
|
delimRef = i;
|
||||||
|
firstDelimPos = delimPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( firstDelimPos == str.length() )
|
||||||
|
{
|
||||||
|
if( str.length() > offset )
|
||||||
|
output.push_back( str.substr( offset, str.length() - offset ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( firstDelimPos > offset )
|
||||||
|
output.push_back( str.substr( offset, firstDelimPos - offset ) );
|
||||||
|
String::split( output, str, delim, firstDelimPos + delim[delimRef].length() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
string trim( const string &str )
|
||||||
|
{
|
||||||
|
string::size_type first = 0,
|
||||||
|
last = str.length();
|
||||||
|
|
||||||
|
if( last == 0 ) return str;
|
||||||
|
|
||||||
|
while( first < last )
|
||||||
|
{
|
||||||
|
if( str[first] == ' ' || str[first] == '\t' || str[first] == '\r' || str[first] == '\n' )
|
||||||
|
++first;
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
|
||||||
|
--last;
|
||||||
|
while( last > first )
|
||||||
|
{
|
||||||
|
if( str[last] == ' ' || str[last] == '\t' || str[last] == '\r' || str[last] == '\n' )
|
||||||
|
--last;
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( first == last ) if( str[first] == ' ' || str[first] == '\t' || str[first] == '\r' || str[first] == '\n' )
|
||||||
|
return "";
|
||||||
|
|
||||||
|
return str.substr( first, (++last) - first );
|
||||||
|
}
|
||||||
|
|
||||||
|
string & toLowerCase( string &output, const string &str )
|
||||||
|
{
|
||||||
|
int length = (int)str.length();
|
||||||
|
output.resize( length );
|
||||||
|
for( int i = 0; i < length; ++i )
|
||||||
|
output[i] = ::std::tolower( str[i], ::std::locale() );
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
string & toLowerCase( string &str )
|
||||||
|
{
|
||||||
|
int length = (int)str.length();
|
||||||
|
for( int i = 0; i < length; ++i )
|
||||||
|
str[i] = ::std::tolower( str[i], ::std::locale() );
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
string & toUpperCase( string &output, const string &str )
|
||||||
|
{
|
||||||
|
int length = (int)str.length();
|
||||||
|
output.resize( length );
|
||||||
|
for( int i = 0; i < length; ++i )
|
||||||
|
output[i] = ::std::toupper( str[i], ::std::locale() );
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
string & toUpperCase( string &str )
|
||||||
|
{
|
||||||
|
int length = (int)str.length();
|
||||||
|
for( int i = 0; i < length; ++i )
|
||||||
|
str[i] = ::std::toupper( str[i], ::std::locale() );
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
string & extractDirPath( string &output, const string &file, char dirDelimeter )
|
||||||
|
{
|
||||||
|
string d = " ";
|
||||||
|
d[0] = dirDelimeter;
|
||||||
|
return String::extractDirPath( output, file, d );
|
||||||
|
}
|
||||||
|
|
||||||
|
string & extractDirPath( string &output, const string &file, const string &dirDelimeter )
|
||||||
|
{
|
||||||
|
string::size_type end = file.find_last_of( dirDelimeter );
|
||||||
|
if( end == string::npos )
|
||||||
|
output = "";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++end;
|
||||||
|
output.resize( end );
|
||||||
|
for( string::size_type i = 0; i < end; ++i )
|
||||||
|
output[i] = file[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
string & replaceCharacters( string &str, char characterToReplace, char newCharacter, const string::size_type &offset, const string::size_type &end )
|
||||||
|
{
|
||||||
|
string::size_type i = offset;
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
i = str.find_first_of( characterToReplace, i );
|
||||||
|
if( i >= end ) break;
|
||||||
|
|
||||||
|
str[i++] = newCharacter;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// STREAM ////////////////////////////////////////////////////////////
|
||||||
|
namespace Stream
|
||||||
|
{
|
||||||
|
float* readFloats( float *output, ::std::istream &input, unsigned int numFloats )
|
||||||
|
{
|
||||||
|
string str;
|
||||||
|
for( unsigned int i = 0; i < numFloats; ++i )
|
||||||
|
{
|
||||||
|
input >> str;
|
||||||
|
output[i] = (float)::std::atof( str.c_str() );
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Utility Collection of Miscellanious Handy Functions
|
||||||
|
// © Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef UTILITIES_H
|
||||||
|
#define UTILITIES_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <istream>
|
||||||
|
#include <vector>
|
||||||
|
#include <locale>
|
||||||
|
|
||||||
|
namespace Utility
|
||||||
|
{
|
||||||
|
namespace String
|
||||||
|
{
|
||||||
|
// note to self: add a whitespaceSplit method?
|
||||||
|
::std::vector<::std::string> & split( ::std::vector<::std::string> &output, const ::std::string &str, char delim, ::std::string::size_type offset = 0 );
|
||||||
|
::std::vector<::std::string> & split( ::std::vector<::std::string> &output, const ::std::string &str, const ::std::string &delim, ::std::string::size_type offset = 0 );
|
||||||
|
::std::vector<::std::string> & split( ::std::vector<::std::string> &output, const ::std::string &str, const ::std::vector<::std::string> &delim, ::std::string::size_type offset = 0 );
|
||||||
|
::std::string trim( const ::std::string &str );
|
||||||
|
::std::string & toLowerCase( ::std::string &output, const ::std::string &str );
|
||||||
|
::std::string & toLowerCase( ::std::string &str );
|
||||||
|
::std::string & toUpperCase( ::std::string &output, const ::std::string &str );
|
||||||
|
::std::string & toUpperCase( ::std::string &str );
|
||||||
|
::std::string & extractDirPath( ::std::string &output, const ::std::string &file, char dirDelimeter );
|
||||||
|
::std::string & extractDirPath( ::std::string &output, const ::std::string &file, const ::std::string &dirDelimeter );
|
||||||
|
::std::string & replaceCharacters( ::std::string &str, char characterToReplace, char newCharacter, const ::std::string::size_type &offset = 0, const ::std::string::size_type &end = ::std::string::npos );
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Stream
|
||||||
|
{
|
||||||
|
float* readFloats( float *output, ::std::istream &input, unsigned int numFloats );
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace StaticArray
|
||||||
|
{
|
||||||
|
template<typename ElementType, unsigned int num>
|
||||||
|
inline unsigned int numElementsOf( const ElementType(&)[num] )
|
||||||
|
{ return num; }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Element
|
||||||
|
{
|
||||||
|
template<typename ElementType>
|
||||||
|
inline void swap( ElementType &elementA, ElementType &elementB, ElementType &swapSpace )
|
||||||
|
{ swapSpace = elementA; elementA = elementB; elementB = swapSpace; }
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
inline void swap( ElementType &elementA, ElementType &elementB )
|
||||||
|
{ ElementType swapSpace; swap( elementA, elementB, swapSpace ); }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Value
|
||||||
|
{
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType abs( const ValueType &value )
|
||||||
|
{ return value < 0 ? value * -1 : value; }
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType max( const ValueType &valueA, const ValueType &valueB )
|
||||||
|
{ return valueA > valueB ? valueA : valueB; }
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType min( const ValueType &valueA, const ValueType &valueB )
|
||||||
|
{ return valueA < valueB ? valueA : valueB; }
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType radian( const ValueType °ree )
|
||||||
|
{ return degree * (3.1415926535897932384626433832795f / 180.0f); }
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType degree( const ValueType &radian )
|
||||||
|
{ return radian * (180.0f / 3.1415926535897932384626433832795f); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,75 @@
|
||||||
|
#include "WinTimer.h"
|
||||||
|
|
||||||
|
using namespace ::Utility;
|
||||||
|
|
||||||
|
namespace PrivateStatic
|
||||||
|
{
|
||||||
|
LARGE_INTEGER ticksPerSecond = { 0 };
|
||||||
|
double secondsPerTick = 0.0f;
|
||||||
|
|
||||||
|
class WatchDog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WatchDog( )
|
||||||
|
{
|
||||||
|
if( QueryPerformanceFrequency( &ticksPerSecond ) > 0 )
|
||||||
|
secondsPerTick = ((double)1.0f) / (double) ticksPerSecond.QuadPart;
|
||||||
|
}
|
||||||
|
} watchDog;
|
||||||
|
}
|
||||||
|
|
||||||
|
WinTimer::WinTimer( ) : isPaused(false)
|
||||||
|
{ this->reset(); }
|
||||||
|
|
||||||
|
void WinTimer::reset( )
|
||||||
|
{
|
||||||
|
this->isPaused = false;
|
||||||
|
this->pauseCount.QuadPart = 0;
|
||||||
|
QueryPerformanceCounter( &this->startTick );
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinTimer::pause( )
|
||||||
|
{
|
||||||
|
if( !this->isPaused )
|
||||||
|
{
|
||||||
|
this->isPaused = true;
|
||||||
|
QueryPerformanceCounter( &this->pauseStart );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinTimer::resume( )
|
||||||
|
{
|
||||||
|
if( this->isPaused )
|
||||||
|
{
|
||||||
|
this->isPaused = false;
|
||||||
|
LARGE_INTEGER currentTick;
|
||||||
|
QueryPerformanceCounter( ¤tTick );
|
||||||
|
this->pauseCount.QuadPart += currentTick.QuadPart - this->pauseStart.QuadPart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double WinTimer::getElapsedSeconds( ) const
|
||||||
|
{
|
||||||
|
if( this->isPaused )
|
||||||
|
{
|
||||||
|
LARGE_INTEGER totalTick = this->pauseStart;
|
||||||
|
totalTick.QuadPart -= this->startTick.QuadPart;
|
||||||
|
totalTick.QuadPart -= this->pauseCount.QuadPart;
|
||||||
|
return PrivateStatic::secondsPerTick * (double)totalTick.QuadPart;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LARGE_INTEGER currentTick;
|
||||||
|
QueryPerformanceCounter( ¤tTick );
|
||||||
|
currentTick.QuadPart -= this->startTick.QuadPart;
|
||||||
|
currentTick.QuadPart -= this->pauseCount.QuadPart;
|
||||||
|
return PrivateStatic::secondsPerTick * (double)currentTick.QuadPart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LARGE_INTEGER WinTimer::getCurrentTick( ) const
|
||||||
|
{
|
||||||
|
LARGE_INTEGER currentTick;
|
||||||
|
QueryPerformanceCounter( ¤tTick );
|
||||||
|
return currentTick;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Instanciable Timer class for windows
|
||||||
|
// © Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef WINTIMER_H
|
||||||
|
#define WINTIMER_H
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
namespace Utility
|
||||||
|
{
|
||||||
|
class WinTimer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WinTimer( );
|
||||||
|
|
||||||
|
void reset( );
|
||||||
|
void pause( );
|
||||||
|
void resume( );
|
||||||
|
|
||||||
|
double getElapsedSeconds( ) const;
|
||||||
|
LARGE_INTEGER getCurrentTick( ) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
LARGE_INTEGER startTick, pauseStart, pauseCount;
|
||||||
|
bool isPaused;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,157 @@
|
||||||
|
#include "Camera.h"
|
||||||
|
//Hack: temp include, calc proj matrix properly later
|
||||||
|
#include "..\Core\CoreIncludes.h"
|
||||||
|
|
||||||
|
using namespace Oyster;
|
||||||
|
using namespace Render;
|
||||||
|
using namespace Oyster::Math;
|
||||||
|
Camera::Camera(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Camera::~Camera(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Math::Float3 Camera::GetPosition() {return pos;}
|
||||||
|
void Camera::SetPosition(Math::Float3 p){ pos=p;}
|
||||||
|
|
||||||
|
//axis
|
||||||
|
Math::Float3 Camera::GetRight() {return right;}
|
||||||
|
Math::Float3 Camera::GetUp() {return up;}
|
||||||
|
Math::Float3 Camera::GetLook() {return look;}
|
||||||
|
|
||||||
|
//frustrum
|
||||||
|
float Camera::GetNearZ(){return nearZ;}
|
||||||
|
float Camera::GetFarZ(){return farZ;}
|
||||||
|
float Camera::GetAspect(){return aspect;}
|
||||||
|
float Camera::GetFovY(){return fovY;}
|
||||||
|
float Camera::GetFovX(){return fovX;}
|
||||||
|
|
||||||
|
//set frustrum
|
||||||
|
void Camera::SetLens(float fovY, float aspect, float zn, float zf)
|
||||||
|
{
|
||||||
|
this->fovY=fovY;
|
||||||
|
this->aspect=aspect;
|
||||||
|
nearZ=zn;
|
||||||
|
farZ=zf;
|
||||||
|
D3DXMATRIX P;
|
||||||
|
D3DXMatrixPerspectiveFovLH(&P,fovY,aspect,zn,zf);
|
||||||
|
mProj = Math::Float4x4(P);
|
||||||
|
}
|
||||||
|
|
||||||
|
//normal LookAt
|
||||||
|
void Camera::LookAt(Math::Float3 pos, Math::Float3 target, Math::Float3 worldUp)
|
||||||
|
{
|
||||||
|
look=target;
|
||||||
|
up=worldUp;
|
||||||
|
this->pos=pos;
|
||||||
|
right = up.cross(look);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get Matrices
|
||||||
|
Matrix Camera::View(){return mView;}
|
||||||
|
Matrix Camera::Proj(){return mProj;}
|
||||||
|
Matrix Camera::ViewProj()
|
||||||
|
{
|
||||||
|
return (mView * mProj).transpose(); // edited by Dan 04-19
|
||||||
|
}
|
||||||
|
|
||||||
|
//Move Camera
|
||||||
|
//FIX: Multiply Add not working
|
||||||
|
//FIX: Single Float Duplicate Creation
|
||||||
|
void Camera::Strafe(float d)
|
||||||
|
{
|
||||||
|
Math::Float3 s= Math::Float3(d,d,d);
|
||||||
|
pos= (Math::operator*(s,right)) + pos;
|
||||||
|
}
|
||||||
|
void Camera::Walk(float d)
|
||||||
|
{
|
||||||
|
Math::Float3 s= Math::Float3(d,d,d);
|
||||||
|
pos= (Math::operator*(s,look)) + pos;
|
||||||
|
}
|
||||||
|
void Camera::Fly(float d)
|
||||||
|
{
|
||||||
|
Math::Float3 s= Math::Float3(d,d,d);
|
||||||
|
pos= (Math::operator*(s,up)) + pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Rotate Camera
|
||||||
|
//FIX: Float3 * float4x4
|
||||||
|
void Camera::Pitch(float angle)
|
||||||
|
{
|
||||||
|
Matrix m;
|
||||||
|
Math::rotationMatrix(m,angle,right);
|
||||||
|
m = m.getAdjoint().getInverse();
|
||||||
|
|
||||||
|
up = (Math::Float4(up,0) * m).xyz;
|
||||||
|
look = (Math::Float4(look,0) * m).xyz;
|
||||||
|
}
|
||||||
|
void Camera::Yaw(float angle)
|
||||||
|
{
|
||||||
|
|
||||||
|
Matrix m;
|
||||||
|
Math::rotationMatrix(m,angle,up);
|
||||||
|
m = m.getAdjoint().getInverse();
|
||||||
|
|
||||||
|
right = (Math::Float4(right,0) * m).xyz;
|
||||||
|
look = (Math::Float4(look,0) * m).xyz;
|
||||||
|
}
|
||||||
|
void Camera::Roll(float angle)
|
||||||
|
{
|
||||||
|
Matrix m;
|
||||||
|
Math::rotationMatrix(m, angle,look);
|
||||||
|
m = m.getAdjoint().getInverse();
|
||||||
|
|
||||||
|
up = (Math::Float4(up,0) * m).xyz;
|
||||||
|
right = (Math::Float4(right,0) * m).xyz;
|
||||||
|
}
|
||||||
|
void Camera::RotateY(float angle)
|
||||||
|
{
|
||||||
|
Matrix m;
|
||||||
|
|
||||||
|
Math::rotationMatrix_AxisY(m, angle);
|
||||||
|
|
||||||
|
m = m.getAdjoint().getInverse();
|
||||||
|
|
||||||
|
up = (Math::Float4(up,0) * m).xyz;
|
||||||
|
look = (Math::Float4(look,0) * m).xyz;
|
||||||
|
right = (Math::Float4(right,0) * m).xyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Camera::UpdateViewMatrix()
|
||||||
|
{
|
||||||
|
look.normalize();
|
||||||
|
|
||||||
|
up = look.cross(right);
|
||||||
|
up.normalize();
|
||||||
|
|
||||||
|
right = up.cross(look);
|
||||||
|
|
||||||
|
float x = -pos.dot(right);
|
||||||
|
float y = -pos.dot(up);
|
||||||
|
float z = -pos.dot(look);
|
||||||
|
|
||||||
|
mView.m[0][0] = right.x;
|
||||||
|
mView.m[1][0] = right.y;
|
||||||
|
mView.m[2][0] = right.z;
|
||||||
|
mView.m[3][0] = x;
|
||||||
|
|
||||||
|
mView.m[0][1] = up.x;
|
||||||
|
mView.m[1][1] = up.y;
|
||||||
|
mView.m[2][1] = up.z;
|
||||||
|
mView.m[3][1] = y;
|
||||||
|
|
||||||
|
mView.m[0][2] = look.x;
|
||||||
|
mView.m[1][2] = look.y;
|
||||||
|
mView.m[2][2] = look.z;
|
||||||
|
mView.m[3][2] = z;
|
||||||
|
|
||||||
|
mView.m[0][3] = 0.0f;
|
||||||
|
mView.m[1][3] = 0.0f;
|
||||||
|
mView.m[2][3] = 0.0f;
|
||||||
|
mView.m[3][3] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "..\Math\OysterMath.h"
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Render
|
||||||
|
{
|
||||||
|
class Camera
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Camera(void);
|
||||||
|
~Camera(void);
|
||||||
|
|
||||||
|
//position
|
||||||
|
Math::Float3 GetPosition();
|
||||||
|
void SetPosition(Math::Float3);
|
||||||
|
|
||||||
|
//axis
|
||||||
|
Math::Float3 GetRight();
|
||||||
|
Math::Float3 GetUp();
|
||||||
|
Math::Float3 GetLook();
|
||||||
|
|
||||||
|
//frustrum
|
||||||
|
float GetNearZ();
|
||||||
|
float GetFarZ();
|
||||||
|
float GetAspect();
|
||||||
|
float GetFovY();
|
||||||
|
float GetFovX();
|
||||||
|
|
||||||
|
//set frustrum
|
||||||
|
void SetLens(float fovY, float aspect, float zn, float zf);
|
||||||
|
|
||||||
|
//normal LookAt
|
||||||
|
void LookAt(Math::Float3 pos, Math::Float3 target, Math::Float3 worldUp);
|
||||||
|
|
||||||
|
//Get Matrices
|
||||||
|
Math::Matrix View();
|
||||||
|
Math::Matrix Proj();
|
||||||
|
Math::Matrix ViewProj();
|
||||||
|
|
||||||
|
//Move Camera
|
||||||
|
void Strafe(float d);
|
||||||
|
void Walk(float d);
|
||||||
|
void Fly(float d);
|
||||||
|
|
||||||
|
//Rotate Camera
|
||||||
|
void Pitch(float angle);
|
||||||
|
void Yaw(float angle);
|
||||||
|
void Roll(float angle);
|
||||||
|
void RotateY(float angle);
|
||||||
|
|
||||||
|
void UpdateViewMatrix();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Math::Vector3 pos, right, up, look;
|
||||||
|
float nearZ,farZ,aspect,fovX,fovY;
|
||||||
|
Math::Matrix mView, mProj;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
#include "Engine\Math\OysterMath.h"
|
||||||
|
|
||||||
|
struct DirectionalLight
|
||||||
|
{
|
||||||
|
Oyster::Math::Float4 Irradiance;
|
||||||
|
Oyster::Math::Float4 Direction;
|
||||||
|
};
|
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
#ifndef Mesh_h
|
||||||
|
#define Mesh_h
|
||||||
|
|
||||||
|
//#include "../Engine.h"
|
||||||
|
|
||||||
|
|
||||||
|
//#include "..\Core\CoreIncludes.h"
|
||||||
|
//#include "..\Core\Buffer.h"
|
||||||
|
#include "OysterMath.h"
|
||||||
|
//#include "ICollideable.h"
|
||||||
|
#include "ModelInfo.h"
|
||||||
|
|
||||||
|
using namespace Oyster::Math;
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Render
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Model
|
||||||
|
{
|
||||||
|
ModelInfo* info;
|
||||||
|
Float4x4 *World;
|
||||||
|
bool Visible;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
#ifndef MODELINFO_h
|
||||||
|
#define MODELINFO_h
|
||||||
|
|
||||||
|
//#include "../Engine.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "..\Core\CoreIncludes.h"
|
||||||
|
#include "..\Core\Buffer.h"
|
||||||
|
//#include "OysterMath.h"
|
||||||
|
//#include "ICollideable.h"
|
||||||
|
|
||||||
|
using namespace Oyster::Math;
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Render
|
||||||
|
{
|
||||||
|
struct ModelInfo
|
||||||
|
{
|
||||||
|
std::vector<ID3D11ShaderResourceView*> Material;
|
||||||
|
Oyster::Buffer Vertices,Indecies;
|
||||||
|
bool Indexed;
|
||||||
|
int VertexCount;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,165 @@
|
||||||
|
#include "Textbox.h"
|
||||||
|
using namespace Oyster::Render;
|
||||||
|
|
||||||
|
//int Textbox::NumTextfields=0;
|
||||||
|
Oyster::Buffer Textbox::TextBuffer;
|
||||||
|
int Textbox::NumLetters;
|
||||||
|
//std::vector<TextInstanceData> Textbox::TextInstances;
|
||||||
|
ID3D11ShaderResourceView* Textbox::Texture=NULL;
|
||||||
|
bool Textbox::Init()
|
||||||
|
{
|
||||||
|
//NumTextfields = 0;
|
||||||
|
//NumVertices = 0;
|
||||||
|
//HRESULT test=HRESULT_FAI
|
||||||
|
if(FAILED(CreateVertexBuffer()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//update(_str, _pos);
|
||||||
|
return true;
|
||||||
|
//return true;
|
||||||
|
}
|
||||||
|
bool Textbox::SetTexture(const char* _file)
|
||||||
|
{
|
||||||
|
if(FAILED(D3DX11CreateShaderResourceViewFromFileA(Oyster::Core::Device, _file, NULL, NULL, &Texture, NULL)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool Textbox::UpdateTextField(std::string _str)
|
||||||
|
{
|
||||||
|
//DEPRECATED
|
||||||
|
//Update(_str);
|
||||||
|
return false;
|
||||||
|
/*UINT _id=TextInstances.size();
|
||||||
|
//TextInstances.resize(_id+1);
|
||||||
|
Text2D newD;
|
||||||
|
TextInstances.push_back(newD);
|
||||||
|
if(FAILED(CreateTextfield(_id)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Update(_id, _str, _pos);
|
||||||
|
TextInstances[_id].Visible=true;
|
||||||
|
TextInstances[_id].World=Float4x4::identity;
|
||||||
|
NumTextfields++;
|
||||||
|
return true;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Textbox::CreateVertexBuffer()
|
||||||
|
{
|
||||||
|
HRESULT result;
|
||||||
|
//Create vertices
|
||||||
|
/*
|
||||||
|
std::vector<TextData> mVertices;
|
||||||
|
mVertices.resize(4);
|
||||||
|
D3DXVECTOR3 testloc=D3DXVECTOR3(0,0,0);
|
||||||
|
mVertices[0].pos = testloc+D3DXVECTOR3(0.0f, 0.0f, 0.0f);
|
||||||
|
mVertices[1].pos = testloc+D3DXVECTOR3(TEXT_SIZE, 0.0f, 0.0f);
|
||||||
|
mVertices[2].pos = testloc+D3DXVECTOR3(0.0f, TEXT_SIZE, 0.0f);
|
||||||
|
mVertices[3].pos = testloc+D3DXVECTOR3(TEXT_SIZE, TEXT_SIZE, 0.0f);
|
||||||
|
float normaloffset=(1.0f/TEXT_NR_LETTERS);
|
||||||
|
mVertices[0].uv=D3DXVECTOR2(normaloffset,1);
|
||||||
|
mVertices[1].uv=D3DXVECTOR2(0,1);
|
||||||
|
mVertices[2].uv=D3DXVECTOR2(normaloffset,0);
|
||||||
|
mVertices[3].uv=D3DXVECTOR2(0,0);
|
||||||
|
*/
|
||||||
|
|
||||||
|
//Oyster::Buffer::BUFFER_INIT_DESC desc;
|
||||||
|
//desc.ElementSize=sizeof(TextData);
|
||||||
|
//desc.NumElements = mVertices.size();
|
||||||
|
//desc.Type = Oyster::Buffer::BUFFER_TYPE::VERTEX_BUFFER;
|
||||||
|
//desc.Usage = Oyster::Buffer::BUFFER_USAGE::BUFFER_DEFAULT;
|
||||||
|
//desc.InitData = &mVertices[0];
|
||||||
|
|
||||||
|
//result=TextBuffer.Init(desc);
|
||||||
|
//NumVertices=mVertices.size();
|
||||||
|
//TextInstances[_id].NumLetters=0;
|
||||||
|
/*Text2D tmp;
|
||||||
|
tmp.coff=0;
|
||||||
|
tmp.offset=0;
|
||||||
|
tmp.Pos=Float2(0,0);*/
|
||||||
|
Oyster::Buffer::BUFFER_INIT_DESC desc;
|
||||||
|
desc.ElementSize=sizeof(Text2D);
|
||||||
|
desc.NumElements = MAX_LETTER_COUNT;
|
||||||
|
desc.Type = Oyster::Buffer::BUFFER_TYPE::VERTEX_BUFFER;
|
||||||
|
desc.Usage = Oyster::Buffer::BUFFER_USAGE::BUFFER_CPU_WRITE_DISCARD;
|
||||||
|
desc.InitData = 0;
|
||||||
|
result=TextBuffer.Init(desc);
|
||||||
|
NumLetters=0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
HRESULT Textbox::CreateTextfield(int _id)
|
||||||
|
{
|
||||||
|
HRESULT result=E_FAIL;
|
||||||
|
/*if (TextInstances.size()>_id)
|
||||||
|
{
|
||||||
|
TextInstances[_id].NumLetters=0;
|
||||||
|
|
||||||
|
Oyster::Buffer::BUFFER_INIT_DESC desc;
|
||||||
|
desc.ElementSize=sizeof(Text2D);
|
||||||
|
desc.NumElements = MAX_LETTER_COUNT;
|
||||||
|
desc.Type = Oyster::Buffer::BUFFER_TYPE::VERTEX_BUFFER;
|
||||||
|
desc.Usage = Oyster::Buffer::BUFFER_USAGE::BUFFER_CPU_WRITE_DISCARD;
|
||||||
|
desc.InitData = 0;
|
||||||
|
|
||||||
|
result=TextInstances[_id].InstanceBuffer.Init(desc);
|
||||||
|
}*/
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
void Textbox::Update(std::string _str, float _xscale)
|
||||||
|
{
|
||||||
|
UINT instances=0;
|
||||||
|
Text2D tmpInst;
|
||||||
|
|
||||||
|
void* dest = TextBuffer.Map();
|
||||||
|
Text2D* dataView = reinterpret_cast<Text2D*>(dest);
|
||||||
|
//tmpInst.charOffset=_pos;
|
||||||
|
for (unsigned int i=0; i<_str.length(); i++)
|
||||||
|
{
|
||||||
|
tmpInst.coff=(1.0f/TEXT_NR_LETTERS);
|
||||||
|
tmpInst.offset=(_str[i]-32);
|
||||||
|
tmpInst.Pos=i*(0.005f*_xscale);
|
||||||
|
//float tst=getCharID(_str[i]);
|
||||||
|
//tmpInst.offset=tst;
|
||||||
|
//tmpInst.charOffset.x=_pos.x-i*TEXT_SIZE;
|
||||||
|
//tmpInst.data=tst;
|
||||||
|
dataView[instances]=tmpInst;
|
||||||
|
instances++;
|
||||||
|
}
|
||||||
|
NumLetters=instances;
|
||||||
|
//TextInstances[_id].NumLetters=instances;
|
||||||
|
TextBuffer.Unmap();
|
||||||
|
}
|
||||||
|
float Textbox::getCharID(char _in)
|
||||||
|
{
|
||||||
|
//int charid=_in;
|
||||||
|
//float charid=((_in-'0')-32);
|
||||||
|
return ((_in-32)*(1.0f/TEXT_NR_LETTERS));
|
||||||
|
//return _in-'0';
|
||||||
|
}
|
||||||
|
void Textbox::Apply(int _id)
|
||||||
|
{
|
||||||
|
//Check if the subset exists, so we don't try to pain something that isn't there resulting in a crash
|
||||||
|
//if (NumTextfields>_id)
|
||||||
|
//{
|
||||||
|
//Oyster::Core::DeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||||
|
//Set the size of each vertex "jump", and the start point for the shader
|
||||||
|
//unsigned int strides[2];
|
||||||
|
//offsets start at 0.
|
||||||
|
//unsigned int offsets[2]={0,0};
|
||||||
|
|
||||||
|
//Load the strides with the size of each type
|
||||||
|
//strides[0] = sizeof(TextData);
|
||||||
|
//strides[1] = sizeof(PerCharData);
|
||||||
|
|
||||||
|
//Create an array which points to the buffers needed.
|
||||||
|
//ID3D11Buffer* bufferPointers[2];
|
||||||
|
//bufferPointers[0] = TextBuffer;
|
||||||
|
//bufferPointers[1] = TextInstances[_id].InstanceBuffer;
|
||||||
|
//Load the vertex buffer into the shader
|
||||||
|
//Oyster::Core::DeviceContext->IASetVertexBuffers(0, 2, bufferPointers, strides, offsets);
|
||||||
|
//Get the basic info of the technique that's loaded
|
||||||
|
//}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "..\Engine.h"
|
||||||
|
const int MAX_LETTER_COUNT=60;
|
||||||
|
const int TEXT_NR_LETTERS=95;
|
||||||
|
const float TEXT_SIZE=2.5;
|
||||||
|
struct Text2D
|
||||||
|
{
|
||||||
|
Oyster::Math::Float Pos;
|
||||||
|
int offset;
|
||||||
|
float coff;
|
||||||
|
};
|
||||||
|
/*struct TextInstanceData
|
||||||
|
{
|
||||||
|
Oyster::Buffer InstanceBuffer;
|
||||||
|
bool Visible;
|
||||||
|
int NumLetters;
|
||||||
|
Oyster::Math::Float4x4 World;
|
||||||
|
};*/
|
||||||
|
/*struct TextData
|
||||||
|
{
|
||||||
|
Oyster::Math::Float3 pos;
|
||||||
|
Oyster::Math::Float2 uv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PerCharData
|
||||||
|
{
|
||||||
|
float data;
|
||||||
|
Oyster::Math::Float3 charOffset;
|
||||||
|
};
|
||||||
|
struct TextInstanceData
|
||||||
|
{
|
||||||
|
Oyster::Buffer InstanceBuffer;
|
||||||
|
bool Visible;
|
||||||
|
int NumLetters;
|
||||||
|
Oyster::Math::Float4x4 World;
|
||||||
|
};*/
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Render
|
||||||
|
{
|
||||||
|
class Textbox
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static float getCharID(char _in);
|
||||||
|
static HRESULT CreateVertexBuffer();
|
||||||
|
static HRESULT CreateTextfield(int _id);
|
||||||
|
public:
|
||||||
|
//static Oyster::Buffer TextBuffer;
|
||||||
|
//static int NumVertices;
|
||||||
|
//static std::vector<TextInstanceData> TextInstances;
|
||||||
|
static Oyster::Buffer TextBuffer;
|
||||||
|
static int NumLetters;
|
||||||
|
static ID3D11ShaderResourceView* Texture;
|
||||||
|
|
||||||
|
static bool Init();
|
||||||
|
static bool UpdateTextField(std::string _str);
|
||||||
|
static bool SetTexture(const char* _file);
|
||||||
|
//Updates a textbox with the certain id
|
||||||
|
static void Update(std::string _str, float _scale);
|
||||||
|
//Removes all old instances and recreates it with the input data
|
||||||
|
static HRESULT Reset(int _count, std::string* _str, Float3* _pos);
|
||||||
|
static void Apply(int _id);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include "Buffers.h"
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Resources
|
||||||
|
{
|
||||||
|
Buffer Buffers::V2DSprites = Buffer();
|
||||||
|
Buffer Buffers::CbufferVS = Buffer();
|
||||||
|
Buffer Buffers::CBufferGs = Buffer();
|
||||||
|
Buffer Buffers::CBufferPipelineCs = Buffer();
|
||||||
|
|
||||||
|
void Buffers::Init()
|
||||||
|
{
|
||||||
|
Buffer::BUFFER_INIT_DESC desc;
|
||||||
|
|
||||||
|
desc.ElementSize=sizeof(Math::Float2);
|
||||||
|
desc.NumElements=1;
|
||||||
|
desc.Type = Buffer::BUFFER_TYPE::VERTEX_BUFFER;
|
||||||
|
desc.Usage = Buffer::BUFFER_USAGE::BUFFER_DEFAULT;
|
||||||
|
desc.InitData = &Math::Float2(0,0);
|
||||||
|
|
||||||
|
V2DSprites.Init(desc);
|
||||||
|
|
||||||
|
desc.Type=Buffer::BUFFER_TYPE::CONSTANT_BUFFER_VS;
|
||||||
|
desc.Usage = Buffer::BUFFER_USAGE::BUFFER_CPU_WRITE_DISCARD;
|
||||||
|
desc.ElementSize=sizeof(Math::Float4x4);
|
||||||
|
desc.InitData=0;
|
||||||
|
|
||||||
|
CbufferVS.Init(desc);
|
||||||
|
|
||||||
|
desc.Type = Buffer::BUFFER_TYPE::CONSTANT_BUFFER_GS;
|
||||||
|
|
||||||
|
CBufferGs.Init(desc);
|
||||||
|
|
||||||
|
desc.ElementSize=sizeof(Oyster::Resources::BufferDefinitions::LightStructureBuffer);
|
||||||
|
desc.NumElements=1;
|
||||||
|
desc.Type = Buffer::BUFFER_TYPE::CONSTANT_BUFFER_CS;
|
||||||
|
desc.Usage = Buffer::BUFFER_USAGE::BUFFER_CPU_WRITE_DISCARD;
|
||||||
|
desc.InitData = NULL;
|
||||||
|
|
||||||
|
CBufferPipelineCs.Init(desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../EngineIncludes.h"
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Resources
|
||||||
|
{
|
||||||
|
struct Buffers
|
||||||
|
{
|
||||||
|
static Buffer V2DSprites;
|
||||||
|
|
||||||
|
static Buffer CbufferVS;
|
||||||
|
|
||||||
|
static Buffer CBufferGs;
|
||||||
|
|
||||||
|
static Buffer CBufferPipelineCs;
|
||||||
|
|
||||||
|
static void Init();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "..\EngineIncludes.h"
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Resources
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace BufferDefinitions
|
||||||
|
{
|
||||||
|
struct LightStructureBuffer
|
||||||
|
{
|
||||||
|
::Oyster::Math::Float4x4 viewMatrix, projectionMatrix;
|
||||||
|
::LinearAlgebra::Vector3<unsigned int> numDispatches;
|
||||||
|
unsigned int reservedPadding;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ScreenTileFrustrum
|
||||||
|
{
|
||||||
|
::Oyster::Math::Float rawElement[6 * 4];
|
||||||
|
};
|
||||||
|
|
||||||
|
class PointLightDescription
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct{ ::Oyster::Math::Float3 center; ::Oyster::Math::Float radius; } pos;
|
||||||
|
::Oyster::Math::Float3 color;
|
||||||
|
::Oyster::Math::Float intensty;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
#include "Manager.h"
|
||||||
|
|
||||||
|
std::unordered_map< std::string, Oyster::Render::ModelInfo*> Oyster::Resources::Manager::loadedModels = std::unordered_map< std::string, Oyster::Render::ModelInfo*>();
|
||||||
|
|
||||||
|
Oyster::Render::Model* Oyster::Resources::Manager::LoadModel(std::string Filename, Matrix Scale)
|
||||||
|
{
|
||||||
|
//TODO: Add redundncy sheck, to ensure not recreating model
|
||||||
|
|
||||||
|
//Loop to find filename
|
||||||
|
|
||||||
|
//If found Return Model
|
||||||
|
|
||||||
|
//else Create Model
|
||||||
|
|
||||||
|
Oyster::FileLoaders::ObjReader *reader = Oyster::FileLoaders::ObjReader::LoadFile(Filename, Scale);
|
||||||
|
Oyster::FileLoaders::ObjReader::Vertex** vertex = new Oyster::FileLoaders::ObjReader::Vertex*[1];
|
||||||
|
int vcount;
|
||||||
|
std::map<std::string,ID3D11ShaderResourceView *> textures;
|
||||||
|
reader->GetVertexData( vertex, vcount, textures );
|
||||||
|
|
||||||
|
Oyster::Buffer::BUFFER_INIT_DESC desc;
|
||||||
|
desc.ElementSize=sizeof(Oyster::FileLoaders::ObjReader::Vertex);
|
||||||
|
desc.NumElements = vcount;
|
||||||
|
desc.InitData = *vertex;
|
||||||
|
desc.Type = Oyster::Buffer::VERTEX_BUFFER;
|
||||||
|
desc.Usage = Oyster::Buffer::BUFFER_DEFAULT;
|
||||||
|
|
||||||
|
ID3D11ShaderResourceView *srv = textures["Diffuse"];
|
||||||
|
|
||||||
|
Oyster::Render::ModelInfo* m = new Oyster::Render::ModelInfo();
|
||||||
|
|
||||||
|
m->Vertices = *(Oyster::Engine::Init::Buffers::CreateBuffer(desc));
|
||||||
|
m->VertexCount = vcount;
|
||||||
|
m->Material.push_back(srv);
|
||||||
|
srv = textures["Specular"];
|
||||||
|
m->Material.push_back(srv);
|
||||||
|
srv = textures["Glow"];
|
||||||
|
m->Material.push_back(srv);
|
||||||
|
m->Indexed=false;
|
||||||
|
|
||||||
|
Oyster::Render::Model* model = new Oyster::Render::Model();
|
||||||
|
model->info=m;
|
||||||
|
model->Visible = true;
|
||||||
|
model->World = &Oyster::Math::Float4x4(Oyster::Math::Float4x4::identity);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../EngineIncludes.h"
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Resources
|
||||||
|
{
|
||||||
|
struct Manager
|
||||||
|
{
|
||||||
|
//Expects to be deleted either trough manager or after a clean
|
||||||
|
static Oyster::Render::Model* LoadModel(std::string Filename, Matrix Scale);
|
||||||
|
static void Clean();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::unordered_map< std::string, Oyster::Render::ModelInfo*> loadedModels;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,228 @@
|
||||||
|
#include "PipelineResources.h"
|
||||||
|
|
||||||
|
using namespace Oyster::Resources;
|
||||||
|
|
||||||
|
ID3D11UnorderedAccessView* PipeLineResourses::TempUav = 0;
|
||||||
|
ID3D11ShaderResourceView* PipeLineResourses::TempSrv = 0;
|
||||||
|
|
||||||
|
ID3D11ShaderResourceView* PipeLineResourses::GeometryOut[5] = {0};
|
||||||
|
ID3D11RenderTargetView* PipeLineResourses::GeometryTarget[5] = {0};
|
||||||
|
|
||||||
|
ID3D11ShaderResourceView* PipeLineResourses::ComputeResources[4] = {0};
|
||||||
|
Oyster::Buffer* PipeLineResourses::Resources[2] = {0};
|
||||||
|
|
||||||
|
ID3D11ShaderResourceView* PipeLineResourses::LightOut[4] = {0};
|
||||||
|
ID3D11UnorderedAccessView* PipeLineResourses::LightTarget[4] = {0};
|
||||||
|
|
||||||
|
ID3D11RenderTargetView* PipeLineResourses::RtvNulls[16] = {0};
|
||||||
|
ID3D11ShaderResourceView* PipeLineResourses::SrvNulls[16] = {0};
|
||||||
|
ID3D11UnorderedAccessView* PipeLineResourses::uavNULL[16] = {0};
|
||||||
|
|
||||||
|
Oyster::Collision::Frustrum* PipeLineResourses::SubFrustrums = 0;
|
||||||
|
int PipeLineResourses::FrustrumSize = 0;
|
||||||
|
LinearAlgebra::Vector3<unsigned int> PipeLineResourses::FrustrumDimensions = LinearAlgebra::Vector3<unsigned int>();
|
||||||
|
|
||||||
|
Oyster::Resources::BufferDefinitions::LightStructureBuffer PipeLineResourses::LightData = Oyster::Resources::BufferDefinitions::LightStructureBuffer();
|
||||||
|
|
||||||
|
void PipeLineResourses::Init()
|
||||||
|
{
|
||||||
|
InitGeometry();
|
||||||
|
|
||||||
|
InitSSAOData();
|
||||||
|
InitSubFrustrums();
|
||||||
|
InitPointLights();
|
||||||
|
InitLightData();
|
||||||
|
|
||||||
|
InitLighting();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipeLineResourses::InitGeometry()
|
||||||
|
{
|
||||||
|
D3D11_TEXTURE2D_DESC Tdesc;
|
||||||
|
Tdesc.Width = Oyster::Window::Size.left;
|
||||||
|
Tdesc.Height = Oyster::Window::Size.bottom;
|
||||||
|
Tdesc.MipLevels = Tdesc.ArraySize = 1;
|
||||||
|
Tdesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||||
|
Tdesc.SampleDesc.Count = 1;
|
||||||
|
Tdesc.SampleDesc.Quality=0;
|
||||||
|
Tdesc.Usage = D3D11_USAGE_DEFAULT;
|
||||||
|
Tdesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
|
||||||
|
Tdesc.CPUAccessFlags = 0;
|
||||||
|
Tdesc.MiscFlags = 0;
|
||||||
|
|
||||||
|
ID3D11Texture2D *pTexture;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
//Geometry stage resourses
|
||||||
|
for( int i = 0; i < 5; ++i )
|
||||||
|
{
|
||||||
|
hr = Oyster::Core::Device->CreateTexture2D( &Tdesc, NULL, &pTexture );
|
||||||
|
hr = Oyster::Core::Device->CreateShaderResourceView(pTexture,0,&GeometryOut[i]);
|
||||||
|
hr = Oyster::Core::Device->CreateRenderTargetView(pTexture,0,&GeometryTarget[i]);
|
||||||
|
pTexture->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipeLineResourses::InitSSAOData()
|
||||||
|
{
|
||||||
|
//create Half Spheres and Random Data
|
||||||
|
|
||||||
|
Oyster::Buffer::BUFFER_INIT_DESC desc;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
int NrOfSamples = Oyster::Engine::States::GetNrOfSSAOSamples();
|
||||||
|
int SampleSpread = Oyster::Engine::States::GetSSAOSampleSpread();
|
||||||
|
|
||||||
|
Oyster::Math::Vector3* kernel = new Oyster::Math::Vector3[ NrOfSamples ];
|
||||||
|
Oyster::Math::Vector3* random = new Oyster::Math::Vector3[ SampleSpread ];
|
||||||
|
|
||||||
|
for(int i = 0; i < NrOfSamples; ++i)
|
||||||
|
{
|
||||||
|
kernel[i] = Oyster::Math::Vector3::null;
|
||||||
|
while( kernel[i] == Oyster::Math::Vector3::null )
|
||||||
|
{
|
||||||
|
kernel[i] = Oyster::Math::Vector3(
|
||||||
|
(float)rand() / (RAND_MAX + 1) * (1 - -1) + -1,
|
||||||
|
(float)rand() / (RAND_MAX + 1) * (1 - -1) + -1,
|
||||||
|
(float)rand() / (RAND_MAX + 1) * (1 - 0) + 0);
|
||||||
|
}
|
||||||
|
kernel[i].normalize();
|
||||||
|
|
||||||
|
float scale = float(i) / float(NrOfSamples);
|
||||||
|
scale = (0.1f*(1 - scale * scale) + 1.0f *( scale * scale));
|
||||||
|
kernel[i] *= scale;
|
||||||
|
|
||||||
|
if( i < SampleSpread)
|
||||||
|
{
|
||||||
|
random[i] = Oyster::Math::Vector3::null;
|
||||||
|
while( random[i] == Oyster::Math::Vector3::null )
|
||||||
|
{
|
||||||
|
random[i] = Oyster::Math::Vector3(
|
||||||
|
(float)rand() / (RAND_MAX + 1) * (1 - -1)+ -1,
|
||||||
|
(float)rand() / (RAND_MAX + 1) * (1 - -1)+ -1,
|
||||||
|
0.0f);
|
||||||
|
}
|
||||||
|
random[i].normalize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
D3D11_TEXTURE1D_DESC T1desc;
|
||||||
|
T1desc.Width = NrOfSamples;
|
||||||
|
T1desc.MipLevels = T1desc.ArraySize = 1;
|
||||||
|
T1desc.Format = DXGI_FORMAT_R32G32B32_FLOAT;
|
||||||
|
T1desc.Usage = D3D11_USAGE_DEFAULT;
|
||||||
|
T1desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||||
|
T1desc.CPUAccessFlags = 0;
|
||||||
|
T1desc.MiscFlags = 0;
|
||||||
|
|
||||||
|
D3D11_SUBRESOURCE_DATA sphere;
|
||||||
|
sphere.pSysMem = kernel;
|
||||||
|
|
||||||
|
D3D11_SUBRESOURCE_DATA rnd;
|
||||||
|
rnd.pSysMem = random;
|
||||||
|
|
||||||
|
|
||||||
|
ID3D11Texture1D *pTexture1[2];
|
||||||
|
|
||||||
|
hr = Oyster::Core::Device->CreateTexture1D( &T1desc, &sphere, &pTexture1[0] );
|
||||||
|
hr = Oyster::Core::Device->CreateShaderResourceView( pTexture1[0], 0, &ComputeResources[3] );
|
||||||
|
pTexture1[0]->Release();
|
||||||
|
delete[] kernel;
|
||||||
|
|
||||||
|
T1desc.Width = SampleSpread;
|
||||||
|
hr = Oyster::Core::Device->CreateTexture1D( &T1desc, &rnd, &pTexture1[1] );
|
||||||
|
hr = Oyster::Core::Device->CreateShaderResourceView( (pTexture1[1]), 0, &ComputeResources[2] );
|
||||||
|
pTexture1[1]->Release();
|
||||||
|
delete[] random;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipeLineResourses::InitSubFrustrums()
|
||||||
|
{
|
||||||
|
FrustrumDimensions.x = (::Oyster::Window::Size.left + 15U) / 16U;
|
||||||
|
FrustrumDimensions.y = (::Oyster::Window::Size.bottom + 15U) / 16U;
|
||||||
|
FrustrumDimensions.z = 1;
|
||||||
|
FrustrumSize = FrustrumDimensions.x * FrustrumDimensions.y * FrustrumDimensions.z;
|
||||||
|
if(SubFrustrums!=0)
|
||||||
|
delete[] SubFrustrums;
|
||||||
|
SubFrustrums = new Frustrum[ FrustrumSize ];
|
||||||
|
|
||||||
|
Oyster::Buffer::BUFFER_INIT_DESC desc;
|
||||||
|
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||||
|
|
||||||
|
//buffer description for SubFrustrums
|
||||||
|
desc.Usage = Oyster::Buffer::BUFFER_CPU_WRITE_DISCARD;
|
||||||
|
desc.Type = Oyster::Buffer::STRUCTURED_BUFFER;
|
||||||
|
desc.ElementSize = sizeof( ::Oyster::Resources::BufferDefinitions::ScreenTileFrustrum);
|
||||||
|
desc.NumElements = FrustrumSize;
|
||||||
|
desc.InitData = NULL;
|
||||||
|
|
||||||
|
//create matching srv
|
||||||
|
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
||||||
|
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||||
|
srvDesc.Buffer.FirstElement = 0;
|
||||||
|
srvDesc.Buffer.NumElements = FrustrumSize;
|
||||||
|
|
||||||
|
PipeLineResourses::Resources[0] = Oyster::Engine::Init::Buffers::CreateBuffer(desc);
|
||||||
|
|
||||||
|
HRESULT hr = Oyster::Core::Device->CreateShaderResourceView( *PipeLineResourses::Resources[0], &srvDesc, &Oyster::Resources::PipeLineResourses::ComputeResources[0] );
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipeLineResourses::InitPointLights()
|
||||||
|
{
|
||||||
|
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||||
|
Oyster::Buffer::BUFFER_INIT_DESC desc;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
//buffer description for pointlight
|
||||||
|
desc.Usage = Oyster::Buffer::BUFFER_CPU_WRITE_DISCARD;
|
||||||
|
desc.Type = Oyster::Buffer::STRUCTURED_BUFFER;
|
||||||
|
desc.ElementSize = sizeof(Oyster::Resources::BufferDefinitions::PointLightDescription);
|
||||||
|
desc.NumElements = Oyster::Engine::States::GetMaxPointlights();
|
||||||
|
desc.InitData = NULL;
|
||||||
|
|
||||||
|
PipeLineResourses::Resources[1] = Oyster::Engine::Init::Buffers::CreateBuffer(desc);
|
||||||
|
|
||||||
|
//create matching srv
|
||||||
|
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
||||||
|
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||||
|
srvDesc.Buffer.FirstElement = 0;
|
||||||
|
srvDesc.Buffer.NumElements = Oyster::Engine::States::GetMaxPointlights();
|
||||||
|
|
||||||
|
hr = Oyster::Core::Device->CreateShaderResourceView( *PipeLineResourses::Resources[1], &srvDesc, &Oyster::Resources::PipeLineResourses::ComputeResources[1] );
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipeLineResourses::InitLightData()
|
||||||
|
{
|
||||||
|
LightData.numDispatches = FrustrumDimensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipeLineResourses::InitLighting()
|
||||||
|
{
|
||||||
|
D3D11_TEXTURE2D_DESC Tdesc;
|
||||||
|
Tdesc.Width = Oyster::Window::Size.left;
|
||||||
|
Tdesc.Height = Oyster::Window::Size.bottom;
|
||||||
|
Tdesc.MipLevels = Tdesc.ArraySize = 1;
|
||||||
|
Tdesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||||
|
Tdesc.SampleDesc.Count = 1;
|
||||||
|
Tdesc.SampleDesc.Quality=0;
|
||||||
|
Tdesc.Usage = D3D11_USAGE_DEFAULT;
|
||||||
|
Tdesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
|
||||||
|
Tdesc.CPUAccessFlags = 0;
|
||||||
|
Tdesc.MiscFlags = 0;
|
||||||
|
|
||||||
|
ID3D11Texture2D *pTexture;
|
||||||
|
HRESULT hr;
|
||||||
|
for(int i = 0; i < 4; ++i )
|
||||||
|
{
|
||||||
|
hr = Oyster::Core::Device->CreateTexture2D( &Tdesc, NULL, &pTexture );
|
||||||
|
hr = Oyster::Core::Device->CreateShaderResourceView( pTexture, 0, &(LightOut[i]) );
|
||||||
|
hr = Oyster::Core::Device->CreateUnorderedAccessView( pTexture, 0, &(LightTarget[i]) );
|
||||||
|
pTexture->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = Oyster::Core::Device->CreateTexture2D( &Tdesc, NULL, &pTexture );
|
||||||
|
hr = Oyster::Core::Device->CreateShaderResourceView( pTexture, 0, &TempSrv );
|
||||||
|
hr = Oyster::Core::Device->CreateUnorderedAccessView( pTexture, 0, &TempUav );
|
||||||
|
pTexture->Release();
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef PipeLineResources_H
|
||||||
|
#define PipeLineResources_H
|
||||||
|
|
||||||
|
#include "..\EngineIncludes.h"
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Resources
|
||||||
|
{
|
||||||
|
struct PipeLineResourses
|
||||||
|
{
|
||||||
|
//0 = Diffuse
|
||||||
|
//1 = Specular
|
||||||
|
//2 = Glow
|
||||||
|
//3 = Pos
|
||||||
|
//4 = Normal
|
||||||
|
static ID3D11ShaderResourceView* GeometryOut[5];
|
||||||
|
static ID3D11RenderTargetView* GeometryTarget[5];
|
||||||
|
|
||||||
|
|
||||||
|
//0 = TileBuffer
|
||||||
|
//1 = PointList
|
||||||
|
//2 = Random
|
||||||
|
//3 = Sphere
|
||||||
|
static ID3D11ShaderResourceView* ComputeResources[4];
|
||||||
|
static Oyster::Buffer* Resources[2];
|
||||||
|
|
||||||
|
|
||||||
|
//0 = Diffuse
|
||||||
|
//1 = Specular
|
||||||
|
//2 = Glow
|
||||||
|
//3 = SSAO
|
||||||
|
static ID3D11ShaderResourceView* LightOut[4];
|
||||||
|
static ID3D11UnorderedAccessView* LightTarget[4];
|
||||||
|
|
||||||
|
//0 = BlurTempStorage
|
||||||
|
static ID3D11UnorderedAccessView* TempUav;
|
||||||
|
static ID3D11ShaderResourceView* TempSrv;
|
||||||
|
|
||||||
|
static ID3D11RenderTargetView* RtvNulls[16];
|
||||||
|
static ID3D11ShaderResourceView* SrvNulls[16];
|
||||||
|
static ID3D11UnorderedAccessView* uavNULL[16];
|
||||||
|
|
||||||
|
static Oyster::Collision::Frustrum* SubFrustrums;
|
||||||
|
static int FrustrumSize;
|
||||||
|
static LinearAlgebra::Vector3<unsigned int> FrustrumDimensions;
|
||||||
|
|
||||||
|
static Oyster::Resources::BufferDefinitions::LightStructureBuffer LightData;
|
||||||
|
|
||||||
|
static void Init();
|
||||||
|
|
||||||
|
static void InitGeometry();
|
||||||
|
|
||||||
|
static void InitSSAOData();
|
||||||
|
static void InitSubFrustrums();
|
||||||
|
static void InitPointLights();
|
||||||
|
static void InitLightData();
|
||||||
|
|
||||||
|
static void InitLighting();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,100 @@
|
||||||
|
#include "ShaderEffects.h"
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Resources
|
||||||
|
{
|
||||||
|
Shader::ShaderEffect ShaderEffects::BasicSprite = Shader::ShaderEffect();
|
||||||
|
Shader::ShaderEffect ShaderEffects::Text2DEffect = Shader::ShaderEffect();
|
||||||
|
Shader::ShaderEffect ShaderEffects::ModelEffect = Shader::ShaderEffect();
|
||||||
|
|
||||||
|
void ShaderEffects::Init()
|
||||||
|
{
|
||||||
|
BasicSprite.IAStage.Topology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
|
||||||
|
BasicSprite.Shaders.Vertex = Oyster::Shader::Get::GetVertex("2D");
|
||||||
|
BasicSprite.Shaders.Geometry = Oyster::Shader::Get::GetGeometry("2D");
|
||||||
|
BasicSprite.Shaders.Pixel = Oyster::Shader::Get::GetPixel("Texture0");
|
||||||
|
|
||||||
|
D3D11_BLEND_DESC blendDesc;
|
||||||
|
blendDesc.AlphaToCoverageEnable=false;
|
||||||
|
blendDesc.IndependentBlendEnable=false;
|
||||||
|
blendDesc.RenderTarget[0].BlendEnable=true;
|
||||||
|
|
||||||
|
blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
|
||||||
|
blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
|
||||||
|
blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
||||||
|
|
||||||
|
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
|
||||||
|
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
|
||||||
|
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_MAX;
|
||||||
|
|
||||||
|
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||||
|
|
||||||
|
ID3D11BlendState* blender;
|
||||||
|
|
||||||
|
Oyster::Core::Device->CreateBlendState(&blendDesc,&blender);
|
||||||
|
|
||||||
|
BasicSprite.RenderStates.BlendState = blender;
|
||||||
|
|
||||||
|
ID3D11InputLayout* layout;
|
||||||
|
|
||||||
|
Oyster::Shader::CreateInputLayout(SpriteVertexDesc,1,Oyster::Shader::Get::GetVertex("2D"),layout);
|
||||||
|
|
||||||
|
BasicSprite.IAStage.Layout = layout;
|
||||||
|
|
||||||
|
Text2DEffect.IAStage.Topology=D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
|
||||||
|
Text2DEffect.Shaders.Vertex = Oyster::Shader::Get::GetVertex("Text");
|
||||||
|
Text2DEffect.Shaders.Geometry = Oyster::Shader::Get::GetGeometry("Text");
|
||||||
|
Text2DEffect.Shaders.Pixel = Oyster::Shader::Get::GetPixel("Texture0");
|
||||||
|
|
||||||
|
Oyster::Shader::CreateInputLayout(Text2DDesc,3,Oyster::Shader::Get::GetVertex("Text"),layout);
|
||||||
|
|
||||||
|
Text2DEffect.IAStage.Layout = layout;
|
||||||
|
|
||||||
|
blendDesc.AlphaToCoverageEnable = true;
|
||||||
|
Oyster::Core::Device->CreateBlendState(&blendDesc,&blender);
|
||||||
|
Text2DEffect.RenderStates.BlendState = blender;
|
||||||
|
|
||||||
|
ModelEffect.IAStage.Topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||||
|
Oyster::Shader::CreateInputLayout(ModelDesc,3,Oyster::Shader::Get::GetVertex("OBJ"),layout);
|
||||||
|
ModelEffect.IAStage.Layout = layout;
|
||||||
|
|
||||||
|
ModelEffect.Shaders.Vertex = Oyster::Shader::Get::GetVertex("OBJ");
|
||||||
|
ModelEffect.Shaders.Pixel = Oyster::Shader::Get::GetPixel("OBJDEF");
|
||||||
|
|
||||||
|
Oyster::Buffer::BUFFER_INIT_DESC desc;
|
||||||
|
|
||||||
|
desc.ElementSize=sizeof(Oyster::Math::Float4x4);
|
||||||
|
desc.NumElements = 1;
|
||||||
|
desc.Usage = Oyster::Buffer::BUFFER_CPU_WRITE_DISCARD;
|
||||||
|
desc.Type = Oyster::Buffer::CONSTANT_BUFFER_VS;
|
||||||
|
desc.InitData = NULL;
|
||||||
|
|
||||||
|
ModelEffect.CBuffers.Vertex.push_back(Oyster::Engine::Init::Buffers::CreateBuffer(desc));
|
||||||
|
ModelEffect.CBuffers.Vertex.push_back(Oyster::Engine::Init::Buffers::CreateBuffer(desc));
|
||||||
|
|
||||||
|
//use Oyster::Resources::Buffers::CbufferVS for per object data
|
||||||
|
//perObject = Oyster::Engine::Init::Buffers::CreateBuffer(desc);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D11_INPUT_ELEMENT_DESC ShaderEffects::SpriteVertexDesc[1] =
|
||||||
|
{
|
||||||
|
{"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
D3D11_INPUT_ELEMENT_DESC ShaderEffects::Text2DDesc[3] =
|
||||||
|
{
|
||||||
|
{"Position",0, DXGI_FORMAT_R32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||||
|
{"Offset",0, DXGI_FORMAT_R32_SINT, 0, 4, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||||
|
{"CharOffset",0, DXGI_FORMAT_R32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
D3D11_INPUT_ELEMENT_DESC ShaderEffects::ModelDesc[3] =
|
||||||
|
{
|
||||||
|
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||||
|
{"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||||
|
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Engine.h"
|
||||||
|
#include "Buffers.h"
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Resources
|
||||||
|
{
|
||||||
|
struct ShaderEffects
|
||||||
|
{
|
||||||
|
static Oyster::Shader::ShaderEffect BasicSprite;
|
||||||
|
static Oyster::Shader::ShaderEffect Text2DEffect;
|
||||||
|
static Oyster::Shader::ShaderEffect ModelEffect;
|
||||||
|
|
||||||
|
static void Init();
|
||||||
|
|
||||||
|
static D3D11_INPUT_ELEMENT_DESC SpriteVertexDesc[1];
|
||||||
|
static D3D11_INPUT_ELEMENT_DESC Text2DDesc[3];
|
||||||
|
static D3D11_INPUT_ELEMENT_DESC ModelDesc[3];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,253 @@
|
||||||
|
#include "Shader.h"
|
||||||
|
#include "../Core/Core.h"
|
||||||
|
#include "Utilities.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::vector<ID3D11PixelShader*> PS;
|
||||||
|
std::map<std::string,int> PSMap;
|
||||||
|
|
||||||
|
std::vector<ID3D11GeometryShader*> GS;
|
||||||
|
std::map<std::string,int> GSMap;
|
||||||
|
|
||||||
|
std::vector<ID3D11ComputeShader*> CS;
|
||||||
|
std::map<std::string,int> CSMap;
|
||||||
|
|
||||||
|
std::vector<ID3D11VertexShader*> VS;
|
||||||
|
std::vector<ID3D10Blob*> VBlob;
|
||||||
|
std::map<std::string,int> VSMap;
|
||||||
|
|
||||||
|
std::stringstream log;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Oyster::Shader::InitShaders(const std::string &name)
|
||||||
|
{
|
||||||
|
std::ifstream input;
|
||||||
|
input.open(name.c_str());
|
||||||
|
std::string s, file,method;
|
||||||
|
std::vector<std::string> line;
|
||||||
|
if(!input.is_open())
|
||||||
|
return false;
|
||||||
|
while(!input.eof())
|
||||||
|
{
|
||||||
|
getline(input,s);
|
||||||
|
line.clear();
|
||||||
|
Utility::String::split(line,s,' ');
|
||||||
|
if(line.size())
|
||||||
|
{
|
||||||
|
if(line[0]=="F")
|
||||||
|
{
|
||||||
|
file = line[1];
|
||||||
|
}
|
||||||
|
if(line[0]=="P")
|
||||||
|
{
|
||||||
|
ID3D10Blob *Shader,*Error;
|
||||||
|
if(!PSMap.count(line[2]))
|
||||||
|
{
|
||||||
|
PSMap[line[2]]=(int)PS.size();
|
||||||
|
ID3D11PixelShader* pixel;
|
||||||
|
if(FAILED(D3DX11CompileFromFileA(file.c_str(),NULL,NULL,line[1].c_str(),"ps_5_0",0,0,NULL,&Shader,&Error,NULL)))
|
||||||
|
{
|
||||||
|
std::string fel = (char*)Error->GetBufferPointer();
|
||||||
|
PSMap.erase(line[2]);
|
||||||
|
Error->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(FAILED(Oyster::Core::Device->CreatePixelShader(Shader->GetBufferPointer(),Shader->GetBufferSize(),NULL,&pixel)))
|
||||||
|
{
|
||||||
|
PSMap.erase(line[2]);
|
||||||
|
Error->Release();
|
||||||
|
Shader->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Shader->Release();
|
||||||
|
PS.push_back(pixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(line[0]=="V")
|
||||||
|
{
|
||||||
|
ID3D10Blob *Shader,*Error;
|
||||||
|
if(!VSMap.count(line[2]))
|
||||||
|
{
|
||||||
|
int i = (int)VS.size();
|
||||||
|
VSMap[line[2]]= i;
|
||||||
|
ID3D11VertexShader* vertex;
|
||||||
|
if(FAILED(D3DX11CompileFromFileA(file.c_str(),NULL,NULL,line[1].c_str(),"vs_5_0",0,0,NULL,&Shader,&Error,NULL)))
|
||||||
|
{
|
||||||
|
log //<< "Shader Compilation Warning(s)/Error(s)\n-----------------------------\n"
|
||||||
|
<< (char*) Error->GetBufferPointer();
|
||||||
|
// << "-----------------------------\n";
|
||||||
|
s = log.str();
|
||||||
|
VSMap.erase(line[2]);
|
||||||
|
Error->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(FAILED(Oyster::Core::Device->CreateVertexShader
|
||||||
|
(Shader->GetBufferPointer(),
|
||||||
|
Shader->GetBufferSize(),
|
||||||
|
NULL,
|
||||||
|
&vertex)))
|
||||||
|
{
|
||||||
|
VSMap.erase(line[2]);
|
||||||
|
Error->Release();
|
||||||
|
Shader->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
VS.push_back(vertex);
|
||||||
|
VBlob.push_back(Shader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(line[0]=="G")
|
||||||
|
{
|
||||||
|
ID3D10Blob *Shader,*Error;
|
||||||
|
if(!GSMap.count(line[2]))
|
||||||
|
{
|
||||||
|
GSMap[line[2]]=(int)GS.size();
|
||||||
|
ID3D11GeometryShader* pixel;
|
||||||
|
if(FAILED(D3DX11CompileFromFileA(file.c_str(),NULL,NULL,line[1].c_str(),"gs_5_0",0,0,NULL,&Shader,&Error,NULL)))
|
||||||
|
{
|
||||||
|
std::string fel = (char*)Error->GetBufferPointer();
|
||||||
|
GSMap.erase(line[2]);
|
||||||
|
Error->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(FAILED(Oyster::Core::Device->CreateGeometryShader(Shader->GetBufferPointer(),Shader->GetBufferSize(),NULL,&pixel)))
|
||||||
|
{
|
||||||
|
GSMap.erase(line[2]);
|
||||||
|
Error->Release();
|
||||||
|
Shader->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Shader->Release();
|
||||||
|
GS.push_back(pixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(line[0]=="C")
|
||||||
|
{
|
||||||
|
ID3D10Blob *Shader,*Error;
|
||||||
|
if(!CSMap.count(line[2]))
|
||||||
|
{
|
||||||
|
CSMap[line[2]]=(int)CS.size();
|
||||||
|
ID3D11ComputeShader* comp;
|
||||||
|
if(FAILED(D3DX11CompileFromFileA(file.c_str(),NULL,NULL,line[1].c_str(),"cs_5_0",0,0,NULL,&Shader,&Error,NULL)))
|
||||||
|
{
|
||||||
|
std::string fel = (char*)Error->GetBufferPointer();
|
||||||
|
CSMap.erase(line[2]);
|
||||||
|
Error->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(FAILED(Oyster::Core::Device->CreateComputeShader(Shader->GetBufferPointer(),Shader->GetBufferSize(),NULL,&comp)))
|
||||||
|
{
|
||||||
|
CSMap.erase(line[2]);
|
||||||
|
Error->Release();
|
||||||
|
Shader->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Shader->Release();
|
||||||
|
CS.push_back(comp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Shader::SetShaderEffect(ShaderEffect se)
|
||||||
|
{
|
||||||
|
Shader::Set::SetPixel(se.Shaders.Pixel);
|
||||||
|
Shader::Set::SetVertex(se.Shaders.Vertex);
|
||||||
|
Shader::Set::SetGeometry(se.Shaders.Geometry);
|
||||||
|
Shader::Set::SetCompute(se.Shaders.Compute);
|
||||||
|
Oyster::Core::DeviceContext->IASetInputLayout(se.IAStage.Layout);
|
||||||
|
Oyster::Core::DeviceContext->IASetPrimitiveTopology(se.IAStage.Topology);
|
||||||
|
for(unsigned int i=0;i<se.CBuffers.Vertex.size();++i)
|
||||||
|
se.CBuffers.Vertex[i]->Apply(i);
|
||||||
|
for(unsigned int i=0;i<se.CBuffers.Geometry.size();++i)
|
||||||
|
se.CBuffers.Geometry[i]->Apply(i);
|
||||||
|
for(unsigned int i=0;i<se.CBuffers.Pixel.size();++i)
|
||||||
|
se.CBuffers.Pixel[i]->Apply(i);
|
||||||
|
Oyster::Core::DeviceContext->RSSetState(se.RenderStates.Rasterizer);
|
||||||
|
Oyster::Core::DeviceContext->PSSetSamplers(0,se.RenderStates.SampleCount,se.RenderStates.SampleState);
|
||||||
|
float test[4] = {0};
|
||||||
|
Oyster::Core::DeviceContext->OMSetBlendState(se.RenderStates.BlendState,test,-1);
|
||||||
|
}
|
||||||
|
void Oyster::Shader::Set::SetPixel(int Index)
|
||||||
|
{
|
||||||
|
if(Index==-1)
|
||||||
|
Oyster::Core::DeviceContext->PSSetShader( NULL,NULL,0);
|
||||||
|
else
|
||||||
|
Oyster::Core::DeviceContext->PSSetShader( PS[Index],NULL,0);
|
||||||
|
}
|
||||||
|
void Oyster::Shader::Set::SetVertex(int Index)
|
||||||
|
{
|
||||||
|
if(Index==-1)
|
||||||
|
Oyster::Core::DeviceContext->VSSetShader(NULL,NULL,0);
|
||||||
|
else
|
||||||
|
Oyster::Core::DeviceContext->VSSetShader(VS[Index],NULL,0);
|
||||||
|
}
|
||||||
|
void Oyster::Shader::Set::SetGeometry(int Index)
|
||||||
|
{
|
||||||
|
if(Index==-1)
|
||||||
|
Oyster::Core::DeviceContext->GSSetShader(NULL,NULL,0);
|
||||||
|
else
|
||||||
|
Oyster::Core::DeviceContext->GSSetShader(GS[Index],NULL,0);
|
||||||
|
}
|
||||||
|
void Oyster::Shader::Set::SetCompute(int Index)
|
||||||
|
{
|
||||||
|
if(Index==-1)
|
||||||
|
Oyster::Core::DeviceContext->CSSetShader(NULL,NULL,0);
|
||||||
|
else
|
||||||
|
Oyster::Core::DeviceContext->CSSetShader(CS[Index],NULL,0);
|
||||||
|
}
|
||||||
|
void Oyster::Shader::Set::SetHull(int Index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void Oyster::Shader::Set::SetDomain(int Index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int Oyster::Shader::Get::GetPixel(std::string Name)
|
||||||
|
{
|
||||||
|
if(PSMap.count(Name))
|
||||||
|
return PSMap[Name];
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int Oyster::Shader::Get::GetVertex(std::string Name)
|
||||||
|
{
|
||||||
|
if(VSMap.count(Name))
|
||||||
|
return VSMap[Name];
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int Oyster::Shader::Get::GetGeometry(std::string Name)
|
||||||
|
{
|
||||||
|
if(GSMap.count(Name))
|
||||||
|
return GSMap[Name];
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int Oyster::Shader::Get::GetCompute(std::string Name)
|
||||||
|
{
|
||||||
|
if(CSMap.count(Name))
|
||||||
|
return CSMap[Name];
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int Oyster::Shader::Get::GetHull(std::string Name)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int Oyster::Shader::Get::GetDomain(std::string Name)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
void Oyster::Shader::CreateInputLayout(const D3D11_INPUT_ELEMENT_DESC *desc, int ElementCount,int VertexIndex,ID3D11InputLayout *&Layout)
|
||||||
|
{
|
||||||
|
if(VertexIndex==-1)
|
||||||
|
{
|
||||||
|
Layout=0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Oyster::Core::Device->CreateInputLayout(desc,ElementCount,VBlob[VertexIndex]->GetBufferPointer(),VBlob[VertexIndex]->GetBufferSize(),&Layout);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "..\Core\Buffer.h"
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
class Shader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct ShaderEffect
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int Pixel,Vertex,Geometry,Compute,Hull,Domain;
|
||||||
|
}Shaders;
|
||||||
|
struct IAStage_
|
||||||
|
{
|
||||||
|
ID3D11InputLayout* Layout;
|
||||||
|
D3D11_PRIMITIVE_TOPOLOGY Topology;
|
||||||
|
}IAStage;
|
||||||
|
struct RenderStates_
|
||||||
|
{
|
||||||
|
ID3D11DepthStencilState *DepthStencil;
|
||||||
|
ID3D11RasterizerState *Rasterizer;
|
||||||
|
ID3D11SamplerState **SampleState;
|
||||||
|
int SampleCount;
|
||||||
|
ID3D11BlendState *BlendState;
|
||||||
|
}RenderStates;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
std::vector<Buffer*> Vertex;
|
||||||
|
std::vector<Buffer*> Geometry;
|
||||||
|
std::vector<Buffer*> Pixel;
|
||||||
|
}CBuffers;
|
||||||
|
ShaderEffect()
|
||||||
|
{
|
||||||
|
RenderStates.BlendState=NULL;
|
||||||
|
RenderStates.DepthStencil=NULL;
|
||||||
|
RenderStates.Rasterizer=NULL;
|
||||||
|
RenderStates.SampleState=NULL;
|
||||||
|
RenderStates.SampleCount=0;
|
||||||
|
Shaders.Compute=-1;
|
||||||
|
Shaders.Domain=-1;
|
||||||
|
Shaders.Geometry=-1;
|
||||||
|
Shaders.Hull=-1;
|
||||||
|
Shaders.Pixel=-1;
|
||||||
|
Shaders.Vertex=-1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static bool InitShaders(const std::string &name = "..\\Shaders\\ShaderConfig.txt");
|
||||||
|
|
||||||
|
static void SetShaderEffect(ShaderEffect);
|
||||||
|
|
||||||
|
static void CreateInputLayout(const D3D11_INPUT_ELEMENT_DESC *desc, int ElementCount,int VertexIndex,ID3D11InputLayout *&Layout);
|
||||||
|
|
||||||
|
struct Set
|
||||||
|
{
|
||||||
|
static void SetPixel(int Index);
|
||||||
|
static void SetVertex(int Index);
|
||||||
|
static void SetGeometry(int Index);
|
||||||
|
static void SetCompute(int Index);
|
||||||
|
static void SetHull(int Index);
|
||||||
|
static void SetDomain(int Index);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Get
|
||||||
|
{
|
||||||
|
static int GetPixel(std::string Name);
|
||||||
|
static int GetVertex(std::string Name);
|
||||||
|
static int GetGeometry(std::string Name);
|
||||||
|
static int GetCompute(std::string Name);
|
||||||
|
static int GetHull(std::string Name);
|
||||||
|
static int GetDomain(std::string Name);
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::stringstream* AccesLog();
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,164 @@
|
||||||
|
#include "Window.h"
|
||||||
|
#include <WindowsX.h>
|
||||||
|
|
||||||
|
using namespace Oyster;
|
||||||
|
|
||||||
|
HWND Window::Handle = NULL;
|
||||||
|
std::stringstream Window::Log = std::stringstream();
|
||||||
|
RECT Window::WindowRect = RECT();
|
||||||
|
RECT Window::Size = RECT();
|
||||||
|
RECT Window::ClientRect = RECT();
|
||||||
|
WNDPROC Window::wndProc = NULL;
|
||||||
|
bool Window::isCaptured = false;
|
||||||
|
bool Window::shouldCapture = false;
|
||||||
|
int Window::OffsetMouseX=0;
|
||||||
|
int Window::OffsetMouseY=0;
|
||||||
|
|
||||||
|
bool Window::init( const LPCSTR appName, const LPCSTR className, const HINSTANCE &hInstance, const int &nCmdShow, WNDPROC wProc, bool handleLoop )
|
||||||
|
{
|
||||||
|
if( Handle != NULL )
|
||||||
|
{
|
||||||
|
Log<< "Faulty Init, First window Exists";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register window class
|
||||||
|
WNDCLASSEXA window = { 0 };
|
||||||
|
window.cbSize = sizeof( WNDCLASSEXA );
|
||||||
|
window.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
|
window.lpfnWndProc = wProc;
|
||||||
|
if(handleLoop)
|
||||||
|
{
|
||||||
|
window.lpfnWndProc = Window::InputMethod;
|
||||||
|
Window::wndProc = wProc;
|
||||||
|
}
|
||||||
|
window.hInstance = hInstance;
|
||||||
|
window.hIcon = LoadIcon( NULL, IDI_APPLICATION );
|
||||||
|
window.hCursor = LoadCursor( NULL, IDC_ARROW );
|
||||||
|
window.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
||||||
|
window.lpszMenuName = NULL;
|
||||||
|
window.lpszClassName = className;
|
||||||
|
|
||||||
|
if( !RegisterClassExA( &window ) )
|
||||||
|
{
|
||||||
|
Log << "Failed to Register Window.\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle = CreateWindowEx( NULL,
|
||||||
|
className,
|
||||||
|
appName,
|
||||||
|
WS_OVERLAPPEDWINDOW,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
800, //rc.right - rc.left,
|
||||||
|
600, //rc.bottom - rc.top,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
hInstance,
|
||||||
|
NULL );
|
||||||
|
|
||||||
|
if( Handle == NULL )
|
||||||
|
{
|
||||||
|
Log << "Failed to Init Window.\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
WINDOWINFO wi;
|
||||||
|
wi.cbSize = sizeof(WINDOWINFO);
|
||||||
|
GetWindowInfo(Handle,&wi);
|
||||||
|
WindowRect = wi.rcClient;
|
||||||
|
Size.right = Size.left = WindowRect.right - WindowRect.left;
|
||||||
|
Size.top = Size.bottom = WindowRect.bottom - WindowRect.top;
|
||||||
|
ClientRect.left= ClientRect.top=0;
|
||||||
|
ClientRect.right = Size.left;
|
||||||
|
ClientRect.bottom = Size.top;
|
||||||
|
ShowWindow( Handle, nCmdShow );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::deFocus( ) { SetFocus( GetDesktopWindow() ); }
|
||||||
|
bool Window::isInFocus( ) { return Handle == GetFocus( ); }
|
||||||
|
bool Window::mouseIsInWindow(POINT point )
|
||||||
|
{
|
||||||
|
return PtInRect( &WindowRect, point )!=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK Window::InputMethod( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
|
||||||
|
{
|
||||||
|
switch (message)
|
||||||
|
{
|
||||||
|
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
Oyster::Input::Controller::KeyPressed(wParam);
|
||||||
|
break;
|
||||||
|
case WM_KEYUP:
|
||||||
|
Oyster::Input::Controller::KeyReleased(wParam);
|
||||||
|
break;
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
if(!isCaptured)
|
||||||
|
if(shouldCapture)
|
||||||
|
SetCapture(Handle);
|
||||||
|
POINT pt;
|
||||||
|
pt.x = GET_X_LPARAM(lParam);
|
||||||
|
pt.y = GET_Y_LPARAM(lParam);
|
||||||
|
if(PtInRect(&ClientRect,pt)!=0)
|
||||||
|
Oyster::Input::Controller::MouseMove(GET_X_LPARAM(lParam)+OffsetMouseX,GET_Y_LPARAM(lParam)+OffsetMouseY);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(shouldCapture)
|
||||||
|
{
|
||||||
|
pt.x = Input::Controller::GetX();
|
||||||
|
pt.y = Input::Controller::GetY();
|
||||||
|
ClientToScreen(Handle, &pt);
|
||||||
|
SetCursorPos(pt.x-OffsetMouseX,pt.y-OffsetMouseY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
case WM_MBUTTONDOWN:
|
||||||
|
case WM_RBUTTONDOWN:
|
||||||
|
case WM_XBUTTONDOWN:
|
||||||
|
{
|
||||||
|
Oyster::Input::Controller::MouseBtnPressed(wParam);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
{
|
||||||
|
Oyster::Input::Controller::MouseBtnReleased(MK_LBUTTON);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_MBUTTONUP:
|
||||||
|
{
|
||||||
|
Oyster::Input::Controller::MouseBtnReleased(MK_MBUTTON);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_RBUTTONUP:
|
||||||
|
{
|
||||||
|
Oyster::Input::Controller::MouseBtnReleased(MK_RBUTTON);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_XBUTTONUP:
|
||||||
|
{
|
||||||
|
Oyster::Input::Controller::MouseBtnReleased(wParam);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return wndProc(hWnd, message, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::CaptureMouse(bool b)
|
||||||
|
{
|
||||||
|
shouldCapture=b;
|
||||||
|
isCaptured=false;
|
||||||
|
if(!b)
|
||||||
|
SetCapture(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::SetMouseOffset(int x,int y)
|
||||||
|
{
|
||||||
|
OffsetMouseX=x;
|
||||||
|
OffsetMouseY=y;
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define NOMINMAX // Because I hate Microsoft now. ~Angry Dan.
|
||||||
|
// http://lolengine.net/blog/2011/3/4/fuck-you-microsoft-near-far-macros
|
||||||
|
|
||||||
|
#include <WinSock2.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <sstream>
|
||||||
|
#include "..\Input\InputController.h"
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Input
|
||||||
|
{
|
||||||
|
class Controller;
|
||||||
|
}
|
||||||
|
class Window
|
||||||
|
{
|
||||||
|
friend class ::Oyster::Input::Controller;
|
||||||
|
private:
|
||||||
|
Window();
|
||||||
|
~Window();
|
||||||
|
static void CaptureMouse(bool b = true);
|
||||||
|
static bool shouldCapture;
|
||||||
|
static bool isCaptured;
|
||||||
|
static int OffsetMouseX;
|
||||||
|
static int OffsetMouseY;
|
||||||
|
public:
|
||||||
|
static bool init( const LPCSTR appName, const LPCSTR className, const HINSTANCE &hInstance,const int &nCmdShow, WNDPROC wProc, bool ManageWindow=false );
|
||||||
|
|
||||||
|
static void deFocus( );
|
||||||
|
static bool isInFocus( );
|
||||||
|
static bool mouseIsInWindow(POINT point );
|
||||||
|
|
||||||
|
static HWND Handle;
|
||||||
|
static std::stringstream Log;
|
||||||
|
static RECT WindowRect;
|
||||||
|
static RECT Size;
|
||||||
|
static RECT ClientRect;
|
||||||
|
static WNDPROC wndProc;
|
||||||
|
|
||||||
|
static LRESULT CALLBACK InputMethod(HWND h,UINT i, WPARAM w,LPARAM l);
|
||||||
|
|
||||||
|
static void SetMouseOffset(int x,int y);
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,154 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "Bullet.h"
|
||||||
|
#include "GameLUA.h"
|
||||||
|
#include "Event.h"
|
||||||
|
#include "Session.h"
|
||||||
|
|
||||||
|
using namespace ::Oyster::Math;
|
||||||
|
using namespace ::Oyster::Collision;
|
||||||
|
using namespace ::GameLogic;
|
||||||
|
|
||||||
|
namespace PrivateStatic
|
||||||
|
{
|
||||||
|
// note current position is actually at the end of the lineOfEffect
|
||||||
|
inline void updatePosition( Ray &trail, const Float &distance )
|
||||||
|
{ trail.origin += trail.direction * distance; }
|
||||||
|
|
||||||
|
inline Float3 posAt( const Ray &ray, const Float &distance )
|
||||||
|
{ return ray.origin + (ray.direction * distance); }
|
||||||
|
}
|
||||||
|
|
||||||
|
Bullet::BulletCollector::BulletCollector( const Line *_sampler, int capacity )
|
||||||
|
: EffectCarrier::Collector(capacity), sampler(_sampler), closest(::std::numeric_limits<Float>::max()) {}
|
||||||
|
|
||||||
|
Bullet::BulletCollector::~BulletCollector( ) {}
|
||||||
|
|
||||||
|
void Bullet::BulletCollector::action( Object *hitObject )
|
||||||
|
{
|
||||||
|
if( this->hitObjects.size() == 0 )
|
||||||
|
{
|
||||||
|
this->closest = this->sampler->ray.collisionDistance;
|
||||||
|
this->hitObjects.push_back( hitObject );
|
||||||
|
this->hitPosW.push_back( PrivateStatic::posAt(this->sampler->ray, this->sampler->ray.collisionDistance) );
|
||||||
|
}
|
||||||
|
else if( this->closest > this->sampler->ray.collisionDistance )
|
||||||
|
{
|
||||||
|
this->closest = this->sampler->ray.collisionDistance;
|
||||||
|
this->hitObjects.push_back( this->hitObjects[0] );
|
||||||
|
this->hitPosW.push_back( this->hitPosW[0] );
|
||||||
|
this->hitObjects[0] = hitObject;
|
||||||
|
this->hitPosW[0] = PrivateStatic::posAt( this->sampler->ray, this->sampler->ray.collisionDistance );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->hitObjects.push_back( hitObject );
|
||||||
|
this->hitPosW.push_back( PrivateStatic::posAt(this->sampler->ray, this->sampler->ray.collisionDistance) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bullet::Bullet( Player *owner, const Float3 &origin, const Float3 &normalizedDirection, const Float &_speed, Weapon::Type weapon, const Float &lifeTime )
|
||||||
|
: EffectCarrier(owner, weapon), lineOfEffect(origin, normalizedDirection, _speed), speed(_speed), lifeCountDown(lifeTime), modelID(-1) {}
|
||||||
|
Bullet::Bullet( const Bullet &bullet ) : EffectCarrier(bullet), lineOfEffect(bullet.lineOfEffect), speed(bullet.speed), lifeCountDown(bullet.lifeCountDown), modelID(bullet.modelID) {}
|
||||||
|
Bullet::~Bullet( ) {}
|
||||||
|
|
||||||
|
Bullet & Bullet::operator = ( const Bullet &bullet )
|
||||||
|
{
|
||||||
|
EffectCarrier::operator=( bullet );
|
||||||
|
this->lineOfEffect = bullet.lineOfEffect;
|
||||||
|
this->speed = bullet.speed;
|
||||||
|
this->lifeCountDown = bullet.lifeCountDown;
|
||||||
|
this->modelID = bullet.modelID;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bullet::setDirection( const Float3 &normalizedVector )
|
||||||
|
{ this->lineOfEffect.ray.direction = normalizedVector; }
|
||||||
|
|
||||||
|
void Bullet::setSpeed( const Float &coordLengthPerSecond )
|
||||||
|
{ this->speed = coordLengthPerSecond; }
|
||||||
|
|
||||||
|
void Bullet::setLifeTime( const Float &seconds )
|
||||||
|
{ this->lifeCountDown = seconds; }
|
||||||
|
|
||||||
|
void Bullet::setModelID( int ID )
|
||||||
|
{ this->modelID = ID; }
|
||||||
|
|
||||||
|
Float3 Bullet::getDirection() const
|
||||||
|
{
|
||||||
|
return this->lineOfEffect.ray.direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
EffectCarrier::State Bullet::update( const Float &deltaTime )
|
||||||
|
{
|
||||||
|
switch( this->state )
|
||||||
|
{
|
||||||
|
case Deployed: this->state = Armed;
|
||||||
|
default: case Armed:
|
||||||
|
if( (this->lifeCountDown -= deltaTime) <= 0.0f )
|
||||||
|
{
|
||||||
|
this->state = Dead;
|
||||||
|
printf("gammal och gaggig\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
::PrivateStatic::updatePosition( this->lineOfEffect.ray, this->lineOfEffect.length );
|
||||||
|
this->lineOfEffect.length = this->speed * deltaTime;
|
||||||
|
}
|
||||||
|
case Dead: break;
|
||||||
|
};
|
||||||
|
|
||||||
|
return this->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ICollideable * Bullet::getVolumeOfEffect( ) const
|
||||||
|
{ return &this->lineOfEffect; }
|
||||||
|
|
||||||
|
EffectCarrier * Bullet::clone( ) const
|
||||||
|
{ return new Bullet(*this); }
|
||||||
|
|
||||||
|
EffectCarrier::Result Bullet::writeToKeyFrame( KeyFrame &buffer ) const
|
||||||
|
{
|
||||||
|
if( buffer.numParticles < (int)::Utility::StaticArray::numElementsOf( buffer.Particle ) )
|
||||||
|
{
|
||||||
|
if( this->modelID >= 0 ) if( this->state != Dead )
|
||||||
|
{
|
||||||
|
buffer.Particle[buffer.numParticles].Head = this->lineOfEffect.ray.origin + (this->lineOfEffect.ray.direction * this->lineOfEffect.length);
|
||||||
|
buffer.Particle[buffer.numParticles].Tail = this->lineOfEffect.ray.origin;
|
||||||
|
buffer.Particle[buffer.numParticles].EffectType = this->modelID;
|
||||||
|
++buffer.numParticles;
|
||||||
|
}
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
return Failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
EffectCarrier::Result Bullet::writeToNetEffect( Network::EffectData &buffer ) const
|
||||||
|
{
|
||||||
|
if( this->modelID >= 0 ) if( this->state != Dead )
|
||||||
|
{
|
||||||
|
buffer.head = this->lineOfEffect.ray.origin + (this->lineOfEffect.ray.direction * /* this->lineOfEffect.length*/ 500);
|
||||||
|
buffer.tail = this->lineOfEffect.ray.origin;
|
||||||
|
buffer.identifier = 0;
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
return Failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
using ::std::vector;
|
||||||
|
EffectCarrier::State Bullet::onHit( const vector<Object*> &target, const vector<Float3> &hitPosW )
|
||||||
|
{
|
||||||
|
this->state = Dead;
|
||||||
|
|
||||||
|
//target[0]->applyDamage( 10, *this->owner );
|
||||||
|
//target[0]->applyForceW( this->lineOfEffect.ray.direction * 100.0f, hitPosW[0] );
|
||||||
|
|
||||||
|
Player *owner = (Player *)this->owner;
|
||||||
|
Event::BulletHit *hitEvent = new Event::BulletHit(owner->getPlayerID(), ((Player *)target[0])->getPlayerID()/*, target[0]->getOrientation().v[3].xyz*/);
|
||||||
|
owner->getSession()->addEvent(hitEvent);
|
||||||
|
|
||||||
|
return EffectCarrier::onHit( target, hitPosW );
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef GAME_BULLET_H
|
||||||
|
#define GAME_BULLET_H
|
||||||
|
|
||||||
|
#include "EffectCarrier.h"
|
||||||
|
#include "Line.h"
|
||||||
|
|
||||||
|
namespace GameLogic
|
||||||
|
{
|
||||||
|
class Bullet : public EffectCarrier
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class BulletCollector : public EffectCarrier::Collector
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BulletCollector( const ::Oyster::Collision::Line *sampler, int capacity = 0 );
|
||||||
|
virtual ~BulletCollector( );
|
||||||
|
virtual void action( Object *hitObject );
|
||||||
|
|
||||||
|
const ::Oyster::Collision::Line *sampler;
|
||||||
|
::Oyster::Math::Float closest;
|
||||||
|
};
|
||||||
|
|
||||||
|
Bullet( Player *owner, const ::Oyster::Math::Float3 &origin, const ::Oyster::Math::Float3 &normalizedDirection, const ::Oyster::Math::Float &speed, Weapon::Type weapon, const ::Oyster::Math::Float &lifeTime = 0.0f );
|
||||||
|
Bullet( const Bullet &bullet );
|
||||||
|
virtual ~Bullet( );
|
||||||
|
|
||||||
|
Bullet & operator = ( const Bullet &bullet );
|
||||||
|
|
||||||
|
void setDirection( const ::Oyster::Math::Float3 &normalizedVector );
|
||||||
|
void setSpeed( const ::Oyster::Math::Float &coordLengthPerSecond );
|
||||||
|
void setLifeTime( const ::Oyster::Math::Float &seconds );
|
||||||
|
void setModelID( int ID );
|
||||||
|
|
||||||
|
Float3 getDirection() const;
|
||||||
|
|
||||||
|
virtual State update( const ::Oyster::Math::Float &deltaTime );
|
||||||
|
virtual const ::Oyster::Collision::ICollideable * getVolumeOfEffect( ) const;
|
||||||
|
virtual EffectCarrier * clone( ) const;
|
||||||
|
|
||||||
|
virtual Result writeToKeyFrame( KeyFrame &buffer ) const;
|
||||||
|
virtual Result writeToNetEffect( Network::EffectData &buffer ) const;
|
||||||
|
virtual Type getType( ) const { return EffectCarrier::Bullet; }
|
||||||
|
|
||||||
|
virtual State onHit( const ::std::vector<Object*> &targets, const ::std::vector<::Oyster::Math::Float3> &hitPosW );
|
||||||
|
|
||||||
|
private:
|
||||||
|
::Oyster::Collision::Line lineOfEffect; // note current position is actually at the end of the lineOfEffect
|
||||||
|
::Oyster::Math::Float speed, lifeCountDown;
|
||||||
|
int modelID;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,67 @@
|
||||||
|
#include "EffectCarrier.h"
|
||||||
|
#include "GameLUA.h"
|
||||||
|
#include "Bullet.h"
|
||||||
|
#include "Event.h"
|
||||||
|
#include "Session.h"
|
||||||
|
|
||||||
|
using namespace ::GameLogic;
|
||||||
|
using ::std::vector;
|
||||||
|
|
||||||
|
// STATIC FACTORIES /////////////////////////////////////////////////
|
||||||
|
EffectCarrier * EffectCarrier::createBullet( Player *owner, Weapon::Type weapon, const Float3 &origin, const Float3 &normalizedDirection, const Float &speed, const Float &lifeTime, const ::std::string &modelRef )
|
||||||
|
{
|
||||||
|
class Bullet *carrier = new class Bullet( owner, origin, normalizedDirection, speed, weapon, lifeTime );
|
||||||
|
|
||||||
|
// TODO have a modelID lib to ask
|
||||||
|
carrier->setModelID( 10240 );
|
||||||
|
|
||||||
|
Event::BulletCreated *bulletEvent = new Event::BulletCreated(owner->getPlayerID(), origin, normalizedDirection);
|
||||||
|
owner->getSession()->addEvent(bulletEvent);
|
||||||
|
|
||||||
|
return carrier;
|
||||||
|
}
|
||||||
|
|
||||||
|
// INSTANCE /////////////////////////////////////////////////////////
|
||||||
|
EffectCarrier::Collector::Collector( int capacity ) : hitObjects(), hitPosW()
|
||||||
|
{
|
||||||
|
if( capacity > 0 )
|
||||||
|
{
|
||||||
|
this->hitObjects.reserve( capacity );
|
||||||
|
this->hitPosW.reserve( capacity );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EffectCarrier::Collector::~Collector( ) {}
|
||||||
|
|
||||||
|
void EffectCarrier::Collector::action( Object *hitObject )
|
||||||
|
{
|
||||||
|
this->hitObjects.push_back( hitObject );
|
||||||
|
this->hitPosW.push_back( hitObject->getOrientation().v[3].xyz );
|
||||||
|
}
|
||||||
|
|
||||||
|
EffectCarrier::EffectCarrier( Object *_owner, Weapon::Type _weapon ) : weapon(_weapon), state(Deployed), owner(_owner) {}
|
||||||
|
EffectCarrier::EffectCarrier( const EffectCarrier &carrier ) : weapon(carrier.weapon), state(carrier.state), owner(carrier.owner) {}
|
||||||
|
EffectCarrier::~EffectCarrier( ) { }
|
||||||
|
|
||||||
|
EffectCarrier & EffectCarrier::operator = ( const EffectCarrier & carrier )
|
||||||
|
{
|
||||||
|
this->weapon = carrier.weapon;
|
||||||
|
this->state = carrier.state;
|
||||||
|
this->owner = carrier.owner;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EffectCarrier::setState( const State &state )
|
||||||
|
{ this->state = state; }
|
||||||
|
|
||||||
|
void EffectCarrier::setWeaponType( Weapon::Type weapon )
|
||||||
|
{ this->weapon = weapon; }
|
||||||
|
|
||||||
|
Object * EffectCarrier::accessOwner( ) const
|
||||||
|
{ return this->owner; }
|
||||||
|
|
||||||
|
EffectCarrier::State EffectCarrier::onHit( const vector<Object*> &targets, const vector<Float3> &hitPosW )
|
||||||
|
{
|
||||||
|
GameLUA::executeOnHitScript( this->weapon, this, targets, hitPosW );
|
||||||
|
return this->state;
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef GAME_EFFECT_H
|
||||||
|
#define GAME_EFFECT_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "OysterCollision.h"
|
||||||
|
#include "OysterGame.h"
|
||||||
|
#include "Object.h"
|
||||||
|
#include "Protocoll.h"
|
||||||
|
#include "Weapon.h"
|
||||||
|
#include "Player.h"
|
||||||
|
#include "NetworkUpdateStructs.h"
|
||||||
|
namespace GameLogic
|
||||||
|
{
|
||||||
|
class EffectCarrier
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum State { Deployed, Armed, Dead };
|
||||||
|
enum Result { Success, Failure };
|
||||||
|
enum Type { Undefined, Bullet };
|
||||||
|
|
||||||
|
class Collector : public ::Oyster::Game::CollisionHandler<Object>::VisitingInstance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Collector( int capacity = 0 );
|
||||||
|
virtual ~Collector( );
|
||||||
|
virtual void action( Object *hitObject );
|
||||||
|
|
||||||
|
::std::vector<Object*> hitObjects;
|
||||||
|
::std::vector<Float3> hitPosW;
|
||||||
|
};
|
||||||
|
|
||||||
|
// STATIC FACTORIES /////////////////////////////////////////
|
||||||
|
|
||||||
|
static EffectCarrier * createBullet( Player *owner,
|
||||||
|
Weapon::Type weapon,
|
||||||
|
const ::Oyster::Math::Float3 &originW,
|
||||||
|
const ::Oyster::Math::Float3 &normalizedDirectionW,
|
||||||
|
const ::Oyster::Math::Float &speed,
|
||||||
|
const ::Oyster::Math::Float &lifeTime,
|
||||||
|
const ::std::string &modelRef );
|
||||||
|
|
||||||
|
// INSTANCE /////////////////////////////////////////////////
|
||||||
|
|
||||||
|
EffectCarrier( Object *owner, Weapon::Type weapon = Weapon::Undefined );
|
||||||
|
EffectCarrier( const EffectCarrier &carrier );
|
||||||
|
virtual ~EffectCarrier( );
|
||||||
|
|
||||||
|
EffectCarrier & operator = ( const EffectCarrier & carrier );
|
||||||
|
|
||||||
|
void setState( const State &state );
|
||||||
|
void setWeaponType( Weapon::Type weapon );
|
||||||
|
|
||||||
|
Object * accessOwner( ) const;
|
||||||
|
|
||||||
|
virtual State update( const ::Oyster::Math::Float &deltaTime ) = 0;
|
||||||
|
virtual State onHit( const ::std::vector<Object*> &targets, const ::std::vector<::Oyster::Math::Float3> &hitPosW );
|
||||||
|
virtual const ::Oyster::Collision::ICollideable * getVolumeOfEffect( ) const = 0;
|
||||||
|
virtual EffectCarrier * clone( ) const = 0;
|
||||||
|
virtual Result writeToKeyFrame( KeyFrame &buffer ) const = 0;
|
||||||
|
virtual Result writeToNetEffect(Network::EffectData &data) const = 0;
|
||||||
|
|
||||||
|
virtual Type getType( ) const { return Undefined; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Weapon::Type weapon;
|
||||||
|
State state;
|
||||||
|
Object *owner;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,297 @@
|
||||||
|
#include "GameLUA.h"
|
||||||
|
#include "Object.h"
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "EffectCarrier.h"
|
||||||
|
#include "Weapon.h"
|
||||||
|
#include "Player.h"
|
||||||
|
#include "Session.h"
|
||||||
|
#include "Bullet.h"
|
||||||
|
|
||||||
|
using namespace ::Oyster::Math;
|
||||||
|
using namespace ::GameLogic;
|
||||||
|
using ::std::vector;
|
||||||
|
using ::std::string;
|
||||||
|
|
||||||
|
lua_State *GameLUA::luaState = NULL;
|
||||||
|
Weapon::Type GameLUA::activeScriptWeapon = Weapon::Undefined;
|
||||||
|
|
||||||
|
namespace GameInterface { void registerBindings(lua_State *lua, const char *nameSpace); }
|
||||||
|
|
||||||
|
Float3 lua_tofloat3(lua_State *lua, int index);
|
||||||
|
void lua_pushfloat3(lua_State *lua, const Float3 &value);
|
||||||
|
template<typename T>
|
||||||
|
void lua_pushstdvector(lua_State *lua, const std::vector<T *> &values);
|
||||||
|
void lua_pushstdvector(lua_State *lua, const std::vector<Float3> &values);
|
||||||
|
|
||||||
|
bool GameLUA::init()
|
||||||
|
{
|
||||||
|
if (luaState == NULL)
|
||||||
|
{
|
||||||
|
luaState = luaL_newstate();
|
||||||
|
luaL_openlibs(luaState);
|
||||||
|
|
||||||
|
GameInterface::registerBindings(luaState, "engine");
|
||||||
|
|
||||||
|
// Load all weapon scripts.
|
||||||
|
for(int i = 0; i < Weapon::Count; i++)
|
||||||
|
{
|
||||||
|
GameLUA::loadScript(Weapon::weapons[i].scriptFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameLUA::release()
|
||||||
|
{
|
||||||
|
if (luaState != NULL)
|
||||||
|
{
|
||||||
|
lua_close(luaState);
|
||||||
|
luaState = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameLUA::loadScript(const std::string &file)
|
||||||
|
{
|
||||||
|
if (luaL_loadfile(luaState, file.c_str()) != LUA_OK)
|
||||||
|
{
|
||||||
|
printf("Failed to load script '%s'\n%s\n", file.c_str(), lua_tostring(luaState, -1));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lua_pcall(luaState, 0, 0, 0) != LUA_OK)
|
||||||
|
{
|
||||||
|
printf("Failed to run script '%s'\n%s\n", file.c_str(), lua_tostring(luaState, -1));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameLUA::executeOnFireScript( Weapon::Type weapon, const Player &owner )
|
||||||
|
{
|
||||||
|
lua_getglobal( luaState, Weapon::weapons[weapon].onFireFunction );
|
||||||
|
|
||||||
|
int numArguments = 1;
|
||||||
|
lua_pushlightuserdata(luaState, (void *)&owner);
|
||||||
|
|
||||||
|
int numReturnValues = 0;
|
||||||
|
|
||||||
|
activeScriptWeapon = weapon;
|
||||||
|
|
||||||
|
if (lua_pcall(luaState, numArguments, numReturnValues, 0) != LUA_OK)
|
||||||
|
printf("Failed to run scriptfunction '%s'\n%s\n", Weapon::weapons[weapon].onFireFunction, lua_tostring(luaState, -1));
|
||||||
|
|
||||||
|
activeScriptWeapon = Weapon::Undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameLUA::executeOnUpdateScript( Weapon::Type weapon, Object *object, const Float &deltaTime )
|
||||||
|
{
|
||||||
|
lua_getglobal( luaState, Weapon::weapons[weapon].onUpdateFunction );
|
||||||
|
|
||||||
|
int numArguments = 2;
|
||||||
|
lua_pushlightuserdata(luaState, object);
|
||||||
|
lua_pushnumber(luaState, deltaTime);
|
||||||
|
|
||||||
|
int numReturnValues = 0;
|
||||||
|
|
||||||
|
activeScriptWeapon = weapon;
|
||||||
|
|
||||||
|
if (lua_pcall(luaState, numArguments, numReturnValues, 0) != LUA_OK)
|
||||||
|
printf("Failed to run scriptfunction '%s'\n%s\n", Weapon::weapons[weapon].onUpdateFunction, lua_tostring(luaState, -1));
|
||||||
|
|
||||||
|
activeScriptWeapon = Weapon::Undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameLUA::executeOnHitScript( Weapon::Type weapon, EffectCarrier *effect, const ::std::vector<Object*> &targets, const vector<Float3> &hitPosW )
|
||||||
|
{
|
||||||
|
lua_getglobal( luaState, Weapon::weapons[weapon].onHitFunction );
|
||||||
|
int numArguments = 4;
|
||||||
|
lua_pushlightuserdata(luaState, effect);
|
||||||
|
lua_pushlightuserdata(luaState, effect->accessOwner());
|
||||||
|
lua_pushstdvector(luaState, targets);
|
||||||
|
lua_pushstdvector(luaState, hitPosW);
|
||||||
|
|
||||||
|
int numReturnValues = 0;
|
||||||
|
|
||||||
|
activeScriptWeapon = weapon;
|
||||||
|
|
||||||
|
if (lua_pcall(luaState, numArguments, numReturnValues, 0) != LUA_OK)
|
||||||
|
printf("Failed to run scriptfunction '%s'\n%s\n", Weapon::weapons[weapon].onHitFunction, lua_tostring(luaState, -1));
|
||||||
|
|
||||||
|
activeScriptWeapon = Weapon::Undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Float3 lua_tofloat3(lua_State *lua, int index)
|
||||||
|
{
|
||||||
|
Float3 value;
|
||||||
|
|
||||||
|
lua_rawgeti(lua, index, 1);
|
||||||
|
value.x = (float)lua_tonumber(lua, -1);
|
||||||
|
lua_pop(lua, 1);
|
||||||
|
|
||||||
|
lua_rawgeti(lua, index, 2);
|
||||||
|
value.y = (float)lua_tonumber(lua, -1);
|
||||||
|
lua_pop(lua, 1);
|
||||||
|
|
||||||
|
lua_rawgeti(lua, index, 3);
|
||||||
|
value.z = (float)lua_tonumber(lua, -1);
|
||||||
|
lua_pop(lua, 1);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lua_pushfloat3(lua_State *lua, const Float3 &value)
|
||||||
|
{
|
||||||
|
lua_createtable(lua, 3, 0);
|
||||||
|
|
||||||
|
lua_pushnumber(lua, value.x);
|
||||||
|
lua_rawseti(lua, -2, 1);
|
||||||
|
lua_pushnumber(lua, value.y);
|
||||||
|
lua_rawseti(lua, -2, 2);
|
||||||
|
lua_pushnumber(lua, value.z);
|
||||||
|
lua_rawseti(lua, -2, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void lua_pushstdvector(lua_State *lua, const std::vector<T *> &values)
|
||||||
|
{
|
||||||
|
lua_createtable(lua, (int)values.size(), 0);
|
||||||
|
|
||||||
|
for(int i = 0; i < (int)values.size(); i++)
|
||||||
|
{
|
||||||
|
lua_pushlightuserdata(lua, values[i]);
|
||||||
|
lua_rawseti(lua, -2, i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void lua_pushstdvector(lua_State *lua, const std::vector<Float3> &values)
|
||||||
|
{
|
||||||
|
lua_createtable(lua, (int)values.size(), 0);
|
||||||
|
|
||||||
|
for(int i = 0; i < (int)values.size(); i++)
|
||||||
|
{
|
||||||
|
lua_pushfloat3(lua, values[i]);
|
||||||
|
lua_rawseti(lua, -2, i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace GameInterface
|
||||||
|
{
|
||||||
|
int applyDamage( lua_State *lua )
|
||||||
|
{
|
||||||
|
Object *object = (Object*)lua_touserdata( lua, -3 );
|
||||||
|
unsigned int magnitude = lua_tounsigned( lua, -2 );
|
||||||
|
Object *attacker = (Object*)lua_touserdata( lua, -1 );
|
||||||
|
|
||||||
|
object->applyDamage( magnitude, *attacker );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int applyHeal( lua_State *lua )
|
||||||
|
{
|
||||||
|
Object *object = (Object*)lua_touserdata( lua, -2 );
|
||||||
|
unsigned int magnitude = lua_tounsigned( lua, -1 );
|
||||||
|
|
||||||
|
object->applyHeal( magnitude );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int applyForce( lua_State *lua )
|
||||||
|
{
|
||||||
|
Object *object = (Object*) lua_touserdata( lua, -3 );
|
||||||
|
Float3 force = lua_tofloat3(lua, -2);
|
||||||
|
Float3 position = lua_tofloat3(lua, -1);
|
||||||
|
|
||||||
|
object->applyForceW( force, position );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int createBullet(lua_State *lua)
|
||||||
|
{
|
||||||
|
Weapon::Type weapon = GameLUA::activeScriptWeapon;
|
||||||
|
|
||||||
|
if (weapon == Weapon::Undefined)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Player *owner = (Player *)lua_touserdata(lua, -6);
|
||||||
|
Float4 position = Float4(lua_tofloat3(lua, -5), 1.0f);
|
||||||
|
Float4 direction = Float4(lua_tofloat3(lua, -4), 0.0f);
|
||||||
|
float speed = (float)lua_tonumber(lua, -3);
|
||||||
|
float lifeTime = (float)lua_tonumber(lua, -2);
|
||||||
|
std::string modelRef = lua_tostring(lua, -1);
|
||||||
|
|
||||||
|
// transform local to world
|
||||||
|
transformVector( position, position, owner->getOrientation() );
|
||||||
|
transformVector( direction, direction, owner->getOrientation() );
|
||||||
|
|
||||||
|
// we want projectiles to move relative to the Players movement at the time
|
||||||
|
direction.xyz *= speed;
|
||||||
|
//direction.xyz += owner->getMovement();
|
||||||
|
speed = direction.xyz.length();
|
||||||
|
direction.xyz /= speed;
|
||||||
|
|
||||||
|
EffectCarrier *bullet = EffectCarrier::createBullet( owner, weapon, position.xyz, direction.xyz, speed, lifeTime, modelRef );
|
||||||
|
owner->getSession()->addEffect(*bullet);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getBulletDirection(lua_State *lua)
|
||||||
|
{
|
||||||
|
Bullet *bullet = (Bullet *)lua_touserdata(lua, -1);
|
||||||
|
|
||||||
|
lua_pushfloat3(lua, bullet->getDirection());
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int setWeaponCooldown(lua_State *lua)
|
||||||
|
{
|
||||||
|
Player *player = (Player *)lua_touserdata(lua, -2);
|
||||||
|
float cooldown = (float)lua_tonumber(lua, -1);
|
||||||
|
|
||||||
|
player->setPrimaryWeaponCooldown(cooldown);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FunctionBinding
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
lua_CFunction function;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const FunctionBinding functionBindings[] =
|
||||||
|
{
|
||||||
|
{"applyDamage", applyDamage},
|
||||||
|
{"applyHeal", applyHeal},
|
||||||
|
{"applyForce", applyForce},
|
||||||
|
{"createBullet", createBullet},
|
||||||
|
{"getBulletDirection", getBulletDirection},
|
||||||
|
{"setWeaponCooldown", setWeaponCooldown},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
void registerBindings(lua_State *lua, const char *nameSpace)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
lua_newtable(lua);
|
||||||
|
|
||||||
|
while(functionBindings[i].name != NULL)
|
||||||
|
{
|
||||||
|
lua_pushstring(lua, functionBindings[i].name);
|
||||||
|
lua_pushcfunction(lua, functionBindings[i].function);
|
||||||
|
|
||||||
|
lua_rawset(lua, -3);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_setglobal(lua, nameSpace);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef GAMELUA_h
|
||||||
|
#define GAMELUA_h
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <lua.hpp>
|
||||||
|
|
||||||
|
#include "EffectCarrier.h"
|
||||||
|
#include "Weapon.h"
|
||||||
|
#include "Player.h"
|
||||||
|
|
||||||
|
namespace GameLogic
|
||||||
|
{
|
||||||
|
class GameLUA
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static bool init();
|
||||||
|
static void release();
|
||||||
|
|
||||||
|
static bool loadScript(const ::std::string &file);
|
||||||
|
|
||||||
|
static void executeOnFireScript( Weapon::Type weapon, const Player &owner );
|
||||||
|
static void executeOnUpdateScript( Weapon::Type weapon, Object *object, const ::Oyster::Math::Float &deltaTime );
|
||||||
|
static void executeOnHitScript( Weapon::Type weapon, EffectCarrier *effect, const ::std::vector<Object*> &targets, const std::vector<Oyster::Math::Float3> &hitPosW );
|
||||||
|
|
||||||
|
static Weapon::Type activeScriptWeapon;
|
||||||
|
private:
|
||||||
|
static lua_State *luaState;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "GameLogic.h"
|
||||||
|
|
||||||
|
using ::std::string;
|
||||||
|
|
||||||
|
namespace GameLogic
|
||||||
|
{
|
||||||
|
Result init( const string &iniFile )
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
#ifndef GAMELOGIC_H
|
||||||
|
#define GAMELOGIC_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "Ship.h"
|
||||||
|
|
||||||
|
namespace GameLogic
|
||||||
|
{
|
||||||
|
enum Result { Success, Failure };
|
||||||
|
Result init( const ::std::string &iniFile );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,300 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/* // TODO
|
||||||
|
<object "painting_0">
|
||||||
|
<displayName>Painting</displayName>
|
||||||
|
hitPoints = 0
|
||||||
|
armour = 0
|
||||||
|
centerOfMass = 0 0 0
|
||||||
|
mass = 0
|
||||||
|
<model>../entities/models/painting_0.obj</model>
|
||||||
|
<description>
|
||||||
|
A painting of a brunette.@@She has brown eyes...
|
||||||
|
</description>
|
||||||
|
<box -0.12763351202 0.566205918789 0.7363961339 0.12763351202 -0.566205918789 -0.7363961339>
|
||||||
|
</box>
|
||||||
|
</object>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "InstanceBlueprint.h"
|
||||||
|
#include "Utilities.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
using namespace ::GameLogic;
|
||||||
|
using namespace ::Oyster::Math;
|
||||||
|
using ::std::string;
|
||||||
|
using ::std::vector;
|
||||||
|
using ::std::ifstream;
|
||||||
|
using ::std::stringstream;
|
||||||
|
|
||||||
|
namespace PrivateStatic
|
||||||
|
{
|
||||||
|
bool seekNextObject( string &idNameOutput, ::std::istream &source )
|
||||||
|
{
|
||||||
|
string str;
|
||||||
|
vector<string> splitString;
|
||||||
|
|
||||||
|
while( !source.eof() )
|
||||||
|
{
|
||||||
|
source >> str;
|
||||||
|
if( str.size() == 0 ) continue;
|
||||||
|
if( str[0] == '#' )
|
||||||
|
{ // rest of line is all commentary
|
||||||
|
::std::getline( source, str );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if( str[0] != '<' ) continue;
|
||||||
|
|
||||||
|
if( str.size() == 1 )
|
||||||
|
{ if( !source.eof() ) source >> str; }
|
||||||
|
else str = str.substr( 1 );
|
||||||
|
|
||||||
|
::Utility::String::toLowerCase( str );
|
||||||
|
if( str != "object" ) continue;
|
||||||
|
|
||||||
|
if( source.eof() ) return false;
|
||||||
|
source >> str;
|
||||||
|
|
||||||
|
::Utility::String::split( splitString, str, '\"' );
|
||||||
|
// since str have no prefix whitespaces, we can safely assume
|
||||||
|
// splitString[0] is the string we want. the rest is garbage.
|
||||||
|
idNameOutput = ::Utility::String::trim( splitString[0] );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fillInstanceBlueprint( InstanceBlueprint &targetMem, ::std::istream &source, const Float4x4 &transform )
|
||||||
|
{
|
||||||
|
string line;
|
||||||
|
vector<string> splitString;
|
||||||
|
vector<string> tagDelims(2);
|
||||||
|
tagDelims[0] = "<";
|
||||||
|
tagDelims[1] = ">";
|
||||||
|
|
||||||
|
Float4 minPoint = Float4( Float3(::std::numeric_limits<Float>::max()), 1.0f ),
|
||||||
|
maxPoint = Float4( Float3(-::std::numeric_limits<Float>::max()), 1.0f ),
|
||||||
|
centerOfMass = Float4( Float3::null, 1.0f );
|
||||||
|
|
||||||
|
while( !source.eof() )
|
||||||
|
{
|
||||||
|
::std::getline( source, line );
|
||||||
|
|
||||||
|
line = ::Utility::String::trim( line );
|
||||||
|
|
||||||
|
if( line.length() == 0 ) continue;
|
||||||
|
if( line[0] == '#' ) continue;
|
||||||
|
|
||||||
|
splitString = vector<string>();
|
||||||
|
::Utility::String::split( splitString, line, '#' );
|
||||||
|
line = ::Utility::String::trim( splitString[0] );
|
||||||
|
|
||||||
|
if( line.length() == 0 )
|
||||||
|
continue; // just to be sure
|
||||||
|
|
||||||
|
if( line[0] == '<' )
|
||||||
|
{ // it's possibly <displayName>, <model>, <box>, <description> or </object>
|
||||||
|
splitString = vector<string>();
|
||||||
|
::Utility::String::split( splitString, line, tagDelims );
|
||||||
|
line = ::Utility::String::toLowerCase( ::Utility::String::trim(splitString[0]) );
|
||||||
|
if( line == "displayname" )
|
||||||
|
{ // <displayName>Painting</displayName>
|
||||||
|
targetMem.name = ::Utility::String::trim(splitString[1]);
|
||||||
|
}
|
||||||
|
else if( line == "model" )
|
||||||
|
{ // <model>../entities/models/painting_0.obj</model>
|
||||||
|
targetMem.objFileName = ::Utility::String::replaceCharacters( ::Utility::String::trim(splitString[1]), '/', '\\' );
|
||||||
|
}
|
||||||
|
else if( line == "description" )
|
||||||
|
{ /* <description>
|
||||||
|
A painting of a brunette.@@She has brown eyes...
|
||||||
|
</description> */
|
||||||
|
|
||||||
|
if( splitString.size() > 1 )
|
||||||
|
line = ::Utility::String::trim( splitString[1] );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( source.eof() ) return;
|
||||||
|
::std::getline( source, line );
|
||||||
|
}
|
||||||
|
|
||||||
|
splitString = vector<string>();
|
||||||
|
::Utility::String::split( splitString, line, "@@" );
|
||||||
|
stringstream strBuilder( splitString[0] );
|
||||||
|
|
||||||
|
vector<string>::size_type numSplits = splitString.size();
|
||||||
|
for( vector<string>::size_type i = 1; i < numSplits; ++i )
|
||||||
|
{
|
||||||
|
if( i > 1 ) strBuilder << '\n';
|
||||||
|
strBuilder << splitString[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
targetMem.description = strBuilder.str();
|
||||||
|
}
|
||||||
|
else if( line.find_first_of("box") == 0 )
|
||||||
|
{ /* <box -0.12763351202 0.566205918789 0.7363961339 0.12763351202 -0.566205918789 -0.7363961339>
|
||||||
|
</box> */
|
||||||
|
|
||||||
|
stringstream stream( line );
|
||||||
|
stream >> line;
|
||||||
|
if( line != "box" )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Float3 point;
|
||||||
|
::Utility::Stream::readFloats( point.element, stream, 3 );
|
||||||
|
minPoint.xyz = ::Utility::Value::min( minPoint.xyz, point );
|
||||||
|
maxPoint.xyz = ::Utility::Value::max( maxPoint.xyz, point );
|
||||||
|
|
||||||
|
::Utility::Stream::readFloats( point.element, stream, 3 );
|
||||||
|
minPoint.xyz = ::Utility::Value::min( minPoint.xyz, point );
|
||||||
|
maxPoint.xyz = ::Utility::Value::max( maxPoint.xyz, point );
|
||||||
|
}
|
||||||
|
else if( line == "/object" )
|
||||||
|
break;
|
||||||
|
|
||||||
|
continue; // no point to continue further down
|
||||||
|
} // end of "if( line[0] == '<' )"
|
||||||
|
|
||||||
|
splitString = vector<string>();
|
||||||
|
|
||||||
|
::Utility::String::split( splitString, line, '=' );
|
||||||
|
if( splitString.size() > 1 )
|
||||||
|
{
|
||||||
|
splitString[0] = ::Utility::String::toLowerCase( ::Utility::String::trim(splitString[0]) );
|
||||||
|
if( splitString[0] == "hitpoints" )
|
||||||
|
{ // hitPoints = 0
|
||||||
|
splitString[1] = ::Utility::String::trim(splitString[1]);
|
||||||
|
targetMem.hullPoints = ::std::atoi( splitString[1].c_str() );
|
||||||
|
}
|
||||||
|
else if( splitString[0] == "armour" ) // ??
|
||||||
|
{ // armour = 0
|
||||||
|
splitString[1] = ::Utility::String::trim(splitString[1]);
|
||||||
|
targetMem.shieldPoints = ::std::atoi( splitString[1].c_str() );
|
||||||
|
}
|
||||||
|
else if( splitString[0] == "mass" )
|
||||||
|
{ // mass = 0
|
||||||
|
splitString[1] = ::Utility::String::trim(splitString[1]);
|
||||||
|
targetMem.mass = (float)::std::atof( splitString[1].c_str() );
|
||||||
|
if( targetMem.mass == 0.0f )
|
||||||
|
targetMem.mass = ::std::numeric_limits<float>::max();
|
||||||
|
}
|
||||||
|
else if( splitString[0] == "centerofmass" )
|
||||||
|
{ // centerOfMass = 0 0 0
|
||||||
|
stringstream stream( splitString[1] );
|
||||||
|
::Utility::Stream::readFloats( centerOfMass.element, stream, 3 );
|
||||||
|
}
|
||||||
|
else if( splitString[0] == "maxspeed" )
|
||||||
|
{ // maxspeed = [ float of top speed: default 400.0 ]
|
||||||
|
stringstream stream( splitString[1] );
|
||||||
|
string value;
|
||||||
|
stream >> value;
|
||||||
|
targetMem.movementProperty.maxSpeed = (float)::std::atof( value.c_str() );
|
||||||
|
}
|
||||||
|
else if( splitString[0] == "deacceleration" )
|
||||||
|
{ // deacceleration = [ float of acceleration : default 50.0 ]
|
||||||
|
stringstream stream( splitString[1] );
|
||||||
|
string value;
|
||||||
|
stream >> value;
|
||||||
|
targetMem.movementProperty.deAcceleration = (float)::std::atof( value.c_str() );
|
||||||
|
}
|
||||||
|
else if( splitString[0] == "forward" )
|
||||||
|
{ // forward = [ float of acceleration : default 50.0 ]
|
||||||
|
stringstream stream( splitString[1] );
|
||||||
|
string value;
|
||||||
|
stream >> value;
|
||||||
|
targetMem.movementProperty.acceleration.forward = (float)::std::atof( value.c_str() );
|
||||||
|
}
|
||||||
|
else if( splitString[0] == "backward" )
|
||||||
|
{ // backward = [ float of acceleration : default 25.0 ]
|
||||||
|
stringstream stream( splitString[1] );
|
||||||
|
string value;
|
||||||
|
stream >> value;
|
||||||
|
targetMem.movementProperty.acceleration.backward = (float)::std::atof( value.c_str() );
|
||||||
|
}
|
||||||
|
else if( splitString[0] == "strafe" )
|
||||||
|
{ // strafe = [ float of acceleration : default 25.0 ]
|
||||||
|
stringstream stream( splitString[1] );
|
||||||
|
string sValue;
|
||||||
|
stream >> sValue;
|
||||||
|
float fValue = (float)::std::atof( sValue.c_str() );
|
||||||
|
targetMem.movementProperty.acceleration.horizontal = fValue;
|
||||||
|
targetMem.movementProperty.acceleration.vertical = fValue;
|
||||||
|
}
|
||||||
|
else if( splitString[0] == "turnspeed" )
|
||||||
|
{ // turnspeed = [ float in degrees : default 90.0 ]
|
||||||
|
stringstream stream( splitString[1] );
|
||||||
|
string sValue;
|
||||||
|
stream >> sValue;
|
||||||
|
float fValue = ::Utility::Value::radian( (float)::std::atof(sValue.c_str()) );
|
||||||
|
targetMem.rotationProperty.maxSpeed = fValue;
|
||||||
|
targetMem.rotationProperty.deAcceleration = 2.0f * fValue;
|
||||||
|
targetMem.rotationProperty.acceleration.pitch = fValue;
|
||||||
|
targetMem.rotationProperty.acceleration.yaw = fValue;
|
||||||
|
targetMem.rotationProperty.acceleration.roll = fValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
targetMem.centerOfMass = transformVector( centerOfMass, centerOfMass, transform ).xyz;
|
||||||
|
|
||||||
|
if( minPoint != Float4( Float3(::std::numeric_limits<Float>::max()), 1.0f ) )
|
||||||
|
if( maxPoint != Float4( Float3(-::std::numeric_limits<Float>::max()), 1.0f ) )
|
||||||
|
{
|
||||||
|
transformVector( minPoint, minPoint, transform );
|
||||||
|
transformVector( maxPoint, maxPoint, transform );
|
||||||
|
|
||||||
|
targetMem.hitBox.position = (maxPoint.xyz - minPoint.xyz) * 0.5f;
|
||||||
|
targetMem.hitBox.halfSize = ::Utility::Value::abs( targetMem.hitBox.position );
|
||||||
|
targetMem.hitBox.position += minPoint.xyz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InstanceBlueprint::Result InstanceBlueprint::loadFromFile( vector<InstanceBlueprint*> &output, vector<string> &idOutput, const string &entityFile, const Float4x4 &transform )
|
||||||
|
{
|
||||||
|
ifstream file( entityFile );
|
||||||
|
|
||||||
|
if( file.is_open() )
|
||||||
|
{
|
||||||
|
string idName, workingDir;
|
||||||
|
::Utility::String::extractDirPath( workingDir, entityFile, '\\' );
|
||||||
|
|
||||||
|
while( PrivateStatic::seekNextObject(idName, file) )
|
||||||
|
{
|
||||||
|
InstanceBlueprint* blueprint = new InstanceBlueprint();
|
||||||
|
PrivateStatic::fillInstanceBlueprint( *blueprint, file, transform );
|
||||||
|
if( blueprint->objFileName.length() > 0 )
|
||||||
|
blueprint->objFileName = workingDir + blueprint->objFileName;
|
||||||
|
output.push_back( blueprint );
|
||||||
|
idOutput.push_back( idName );
|
||||||
|
}
|
||||||
|
file.close( );
|
||||||
|
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
else return Failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
InstanceBlueprint::InstanceBlueprint( )
|
||||||
|
: name(), objFileName(), description(), mass(::std::numeric_limits<float>::max()), centerOfMass(Float3::null),
|
||||||
|
hullPoints(255), shieldPoints(255)
|
||||||
|
{
|
||||||
|
this->hitBox.halfSize = Float3::null;
|
||||||
|
this->hitBox.position = Float3::null;
|
||||||
|
|
||||||
|
this->movementProperty.maxSpeed = 400.0f;
|
||||||
|
this->movementProperty.deAcceleration = 50.0f;
|
||||||
|
this->movementProperty.acceleration.forward = 50.0f;
|
||||||
|
this->movementProperty.acceleration.backward = 25.0f;
|
||||||
|
this->movementProperty.acceleration.horizontal = 25.0f;
|
||||||
|
this->movementProperty.acceleration.vertical = 25.0f;
|
||||||
|
|
||||||
|
this->rotationProperty.maxSpeed = ::Utility::Value::radian( 90.0f );
|
||||||
|
this->rotationProperty.deAcceleration = ::Utility::Value::radian( 180.0f );
|
||||||
|
this->rotationProperty.acceleration.pitch = ::Utility::Value::radian( 90.0f );
|
||||||
|
this->rotationProperty.acceleration.yaw = ::Utility::Value::radian( 90.0f );
|
||||||
|
this->rotationProperty.acceleration.roll = ::Utility::Value::radian( 90.0f );
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef GAME_INSTANCEBLUEPRINT_H
|
||||||
|
#define GAME_INSTANCEBLUEPRINT_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "OysterMath.h"
|
||||||
|
|
||||||
|
namespace GameLogic
|
||||||
|
{
|
||||||
|
struct InstanceBlueprint
|
||||||
|
{
|
||||||
|
enum Result { Success, Failure };
|
||||||
|
static Result loadFromFile( ::std::vector<InstanceBlueprint*> &output, ::std::vector<::std::string> &idOutput, const ::std::string &entityFile, const ::Oyster::Math::Float4x4 &transform = ::Oyster::Math::Float4x4::identity );
|
||||||
|
|
||||||
|
::std::string name, objFileName, description;
|
||||||
|
float mass;
|
||||||
|
::Oyster::Math::Float3 centerOfMass;
|
||||||
|
struct { ::Oyster::Math::Float3 halfSize, position; } hitBox;
|
||||||
|
// engineData
|
||||||
|
int hullPoints, shieldPoints;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
::Oyster::Math::Float maxSpeed, deAcceleration;
|
||||||
|
struct{ ::Oyster::Math::Float forward, backward, horizontal, vertical; } acceleration;
|
||||||
|
} movementProperty;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
::Oyster::Math::Float maxSpeed, deAcceleration;
|
||||||
|
struct{ ::Oyster::Math::Float pitch, yaw, roll; } acceleration;
|
||||||
|
} rotationProperty;
|
||||||
|
|
||||||
|
InstanceBlueprint( );
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,46 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef GAME_MOVEABLE_H
|
||||||
|
#define GAME_MOVEABLE_H
|
||||||
|
|
||||||
|
#include "OysterMath.h"
|
||||||
|
|
||||||
|
namespace Game
|
||||||
|
{
|
||||||
|
using namespace Oyster::Math;
|
||||||
|
|
||||||
|
class MoveAble
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MoveAble( );
|
||||||
|
MoveAble( const Float4x4 &orientation, const Float3 ¢erOfMass = Float3::null );
|
||||||
|
virtual ~MoveAble( );
|
||||||
|
|
||||||
|
void move( const Float3 &movement, const Float3 &displacement );
|
||||||
|
void move( const Float3 &movement );
|
||||||
|
void turn( const Float3 &deltaAngular );
|
||||||
|
void stop( );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct{ Float4x4 orientation; };
|
||||||
|
struct{ Float3 axisX; Float paddingX;
|
||||||
|
Float3 axisY; Float paddingY;
|
||||||
|
Float3 axisZ; Float paddingZ;
|
||||||
|
Float3 position; Float paddingP; };
|
||||||
|
};
|
||||||
|
Float3 centerOfMass;
|
||||||
|
|
||||||
|
void updateOrientation( );
|
||||||
|
|
||||||
|
private:
|
||||||
|
Float3 sumDeltaAngular,
|
||||||
|
sumMovement;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,485 @@
|
||||||
|
#include "Object.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
using namespace ::Oyster::Math;
|
||||||
|
using namespace ::Oyster::Collision;
|
||||||
|
using namespace ::Oyster::Game;
|
||||||
|
using ::std::string;
|
||||||
|
using ::std::vector;
|
||||||
|
using ::std::map;
|
||||||
|
|
||||||
|
namespace GameLogic
|
||||||
|
{
|
||||||
|
namespace PrivateStatic
|
||||||
|
{
|
||||||
|
struct EntityFileState
|
||||||
|
{
|
||||||
|
bool isLoaded;
|
||||||
|
vector<unsigned int> bluePrintRef;
|
||||||
|
EntityFileState() : isLoaded(false), bluePrintRef() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
map<string, EntityFileState> loadedEntityFileLibrary;
|
||||||
|
map<string, unsigned int> blueprintIndex = map<string, unsigned int>();
|
||||||
|
vector<InstanceBlueprint*> blueprint = vector<InstanceBlueprint*>();
|
||||||
|
const InstanceBlueprint invalidBluePrint = InstanceBlueprint();
|
||||||
|
unsigned int numCreatedObjects = 0;
|
||||||
|
|
||||||
|
class WatchDog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WatchDog( ) {}
|
||||||
|
~WatchDog( )
|
||||||
|
{
|
||||||
|
vector<InstanceBlueprint*>::size_type numBluePrints = PrivateStatic::blueprint.size();
|
||||||
|
for( vector<InstanceBlueprint*>::size_type i = 0; i < numBluePrints; ++i ) delete PrivateStatic::blueprint[i];
|
||||||
|
}
|
||||||
|
} watchDog;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned int Object::invalidID = ::std::numeric_limits<unsigned int>::max();
|
||||||
|
|
||||||
|
Object::Result Object::init( const string &iniFile )
|
||||||
|
{/*
|
||||||
|
if( PrivateStatic::blueprint.size() > 0 )
|
||||||
|
{ // ReInit friendly
|
||||||
|
vector<InstanceBlueprint*>::size_type numBluePrints = PrivateStatic::blueprint.size();
|
||||||
|
for( vector<InstanceBlueprint*>::size_type i = 0; i < numBluePrints; ++i ) delete PrivateStatic::blueprint[i];
|
||||||
|
PrivateStatic::blueprint = vector<InstanceBlueprint*>();
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// remove?
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object::Result Object::importEntities( vector<unsigned int> &outputConfigID, const string &entityFile, const Float4x4 &transform )
|
||||||
|
{
|
||||||
|
outputConfigID.resize( 0 );
|
||||||
|
|
||||||
|
PrivateStatic::EntityFileState *entityFileState = &PrivateStatic::loadedEntityFileLibrary[entityFile];
|
||||||
|
|
||||||
|
if( entityFileState->isLoaded )
|
||||||
|
{
|
||||||
|
outputConfigID = entityFileState->bluePrintRef;
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<InstanceBlueprint*> loadedBlueprint;
|
||||||
|
vector<string> loadedBlueprintRefNames;
|
||||||
|
if( InstanceBlueprint::loadFromFile( loadedBlueprint, loadedBlueprintRefNames, entityFile, transform ) == InstanceBlueprint::Success )
|
||||||
|
{
|
||||||
|
vector<InstanceBlueprint*>::size_type i = 0,
|
||||||
|
numLoaded = loadedBlueprint.size();
|
||||||
|
|
||||||
|
for( ; i < numLoaded; ++i )
|
||||||
|
{
|
||||||
|
outputConfigID.push_back( (unsigned int)PrivateStatic::blueprint.size() );
|
||||||
|
PrivateStatic::blueprintIndex[ ::Utility::String::toLowerCase(loadedBlueprintRefNames[i]) ] = (unsigned int)PrivateStatic::blueprint.size();
|
||||||
|
PrivateStatic::blueprint.push_back( loadedBlueprint[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
entityFileState->isLoaded = true;
|
||||||
|
entityFileState->bluePrintRef = outputConfigID;
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
return Failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::clearEntityresources( )
|
||||||
|
{
|
||||||
|
PrivateStatic::loadedEntityFileLibrary.clear();
|
||||||
|
|
||||||
|
vector<InstanceBlueprint*>::size_type numBluePrints = PrivateStatic::blueprint.size();
|
||||||
|
for( vector<InstanceBlueprint*>::size_type i = 0; i < numBluePrints; ++i )
|
||||||
|
delete PrivateStatic::blueprint[i];
|
||||||
|
|
||||||
|
PrivateStatic::blueprint.resize( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Object::getNumObjectsCreated( )
|
||||||
|
{ return PrivateStatic::numCreatedObjects; }
|
||||||
|
|
||||||
|
const InstanceBlueprint & Object::getConfig( unsigned int id )
|
||||||
|
{
|
||||||
|
if( id < PrivateStatic::blueprint.size() )
|
||||||
|
return *PrivateStatic::blueprint[id];
|
||||||
|
else
|
||||||
|
return PrivateStatic::invalidBluePrint;
|
||||||
|
}
|
||||||
|
|
||||||
|
const InstanceBlueprint & Object::getConfig( const ::std::string &handle )
|
||||||
|
{
|
||||||
|
map<string, unsigned int>::const_iterator i = PrivateStatic::blueprintIndex.find( ::Utility::String::toLowerCase(string(handle)) );
|
||||||
|
if( i != PrivateStatic::blueprintIndex.end() )
|
||||||
|
return *PrivateStatic::blueprint[i->second];
|
||||||
|
else
|
||||||
|
return PrivateStatic::invalidBluePrint;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::onCollisionAction( Object *visitor, Object *hitEntity )
|
||||||
|
{
|
||||||
|
if( visitor == hitEntity ) return;
|
||||||
|
if( visitor->body.Intersects( &hitEntity->body ) )
|
||||||
|
{
|
||||||
|
Float3 pushVector = (visitor->body.orientation.v[3].xyz - hitEntity->body.orientation.v[3].xyz).getNormalized();
|
||||||
|
pushVector = vectorProjection( visitor->speed, pushVector );
|
||||||
|
pushVector *= 2.0f;
|
||||||
|
visitor->speed -= pushVector;
|
||||||
|
visitor->acceleration=Float3::null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// INSTANCE /////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
Object::Object( )
|
||||||
|
: MoveAble(), objectID(PrivateStatic::numCreatedObjects++), configID(Object::invalidID),
|
||||||
|
physicsID(CollisionHandler<Object>::Reference::invalid), mass(1.0f), disableReduceMovementCount(0),
|
||||||
|
disableReduceRotationCount(0), scaling(1.0f, 1.0f, 1.0f), view(Float4x4::identity), world(Float4x4::identity), viewIsOutOfDate(true), worldIsOutOfDate(true)
|
||||||
|
{
|
||||||
|
this->movementProperty.maxSpeed = this->movementProperty.deAcceleration = this->movementProperty.acceleration.forward = this->movementProperty.acceleration.backward = this->movementProperty.acceleration.horizontal = this->movementProperty.acceleration.vertical = 0.0f;
|
||||||
|
this->rotationProperty.maxSpeed = this->rotationProperty.deAcceleration = this->rotationProperty.acceleration.pitch = this->rotationProperty.acceleration.yaw = this->rotationProperty.acceleration.roll = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object::Object( const Object &object )
|
||||||
|
: MoveAble(object), objectID(object.objectID), configID(object.configID), physicsID(object.physicsID), mass(object.mass),
|
||||||
|
movementProperty(object.movementProperty), rotationProperty(object.rotationProperty),
|
||||||
|
disableReduceMovementCount(object.disableReduceMovementCount), disableReduceRotationCount(object.disableReduceRotationCount),
|
||||||
|
scaling(object.scaling), view(object.view), world(object.world), viewIsOutOfDate(object.viewIsOutOfDate), worldIsOutOfDate(object.worldIsOutOfDate) {}
|
||||||
|
|
||||||
|
Object::Object( const Float4x4 &orientation, const Float3 ¢erOfMass )
|
||||||
|
: MoveAble(orientation, centerOfMass), objectID(PrivateStatic::numCreatedObjects++), configID(invalidID),
|
||||||
|
physicsID(CollisionHandler<Object>::Reference::invalid), mass(1.0f), disableReduceMovementCount(0),
|
||||||
|
disableReduceRotationCount(0), scaling(1.0f, 1.0f, 1.0f), view(Float4x4::identity), world(Float4x4::identity), viewIsOutOfDate(true), worldIsOutOfDate(true)
|
||||||
|
{ this->movementProperty.maxSpeed = this->movementProperty.deAcceleration = this->movementProperty.acceleration.forward = this->movementProperty.acceleration.backward = this->movementProperty.acceleration.horizontal = this->movementProperty.acceleration.vertical = 0.0f; }
|
||||||
|
|
||||||
|
Object::Object( const Box &body, const Float3 ¢erOfMass )
|
||||||
|
: MoveAble(body, centerOfMass), objectID(PrivateStatic::numCreatedObjects++), configID(invalidID),
|
||||||
|
physicsID(CollisionHandler<Object>::Reference::invalid), mass(1.0f), disableReduceMovementCount(0),
|
||||||
|
disableReduceRotationCount(0), scaling(1.0f, 1.0f, 1.0f), view(Float4x4::identity), world(Float4x4::identity), viewIsOutOfDate(true), worldIsOutOfDate(true)
|
||||||
|
{
|
||||||
|
this->movementProperty.maxSpeed = this->movementProperty.deAcceleration = this->movementProperty.acceleration.forward = this->movementProperty.acceleration.backward = this->movementProperty.acceleration.horizontal = this->movementProperty.acceleration.vertical = 0.0f;
|
||||||
|
this->rotationProperty.maxSpeed = this->rotationProperty.deAcceleration = this->rotationProperty.acceleration.pitch = this->rotationProperty.acceleration.yaw = this->rotationProperty.acceleration.roll = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object::~Object( ) {}
|
||||||
|
|
||||||
|
Object & Object::operator = ( const Object &object )
|
||||||
|
{
|
||||||
|
MoveAble::operator=(object);
|
||||||
|
this->objectID = object.objectID;
|
||||||
|
this->configID = object.configID;
|
||||||
|
this->physicsID = object.physicsID;
|
||||||
|
this->mass = object.mass;
|
||||||
|
this->movementProperty = object.movementProperty;
|
||||||
|
this->rotationProperty = object.rotationProperty;
|
||||||
|
this->disableReduceMovementCount = object.disableReduceMovementCount;
|
||||||
|
this->disableReduceRotationCount = object.disableReduceRotationCount;
|
||||||
|
this->scaling = object.scaling;
|
||||||
|
|
||||||
|
if( !object.viewIsOutOfDate )
|
||||||
|
this->view = object.view;
|
||||||
|
if( !object.worldIsOutOfDate )
|
||||||
|
this->world = object.world;
|
||||||
|
this->viewIsOutOfDate = object.viewIsOutOfDate;
|
||||||
|
this->worldIsOutOfDate = object.worldIsOutOfDate;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object * Object::clone( ) const
|
||||||
|
{ return new Object(*this); }
|
||||||
|
|
||||||
|
Object::Type Object::getType( ) const
|
||||||
|
{ return Undefined; }
|
||||||
|
|
||||||
|
const unsigned int & Object::getObjectID( ) const
|
||||||
|
{ return this->objectID; }
|
||||||
|
|
||||||
|
const unsigned int & Object::getConfigID( ) const
|
||||||
|
{ return this->configID; }
|
||||||
|
|
||||||
|
const CollisionHandler<Object>::Reference & Object::getPhysicsID( ) const
|
||||||
|
{ return this->physicsID; }
|
||||||
|
|
||||||
|
const Float & Object::getMass( ) const
|
||||||
|
{ return this->mass; }
|
||||||
|
|
||||||
|
const Float3 & Object::getCenterOfMass( ) const
|
||||||
|
{ return this->rotationPivot; }
|
||||||
|
|
||||||
|
Float3 Object::getInertia( const Float3 &offset ) const
|
||||||
|
{ return MoveAble::getMovement( offset ) *= this->mass; }
|
||||||
|
|
||||||
|
const Box & Object::getCollisionBox( ) const
|
||||||
|
{ return this->body; }
|
||||||
|
|
||||||
|
bool Object::isActive( ) const
|
||||||
|
{ return this->physicsID.isActive(); }
|
||||||
|
|
||||||
|
void Object::setConfig( unsigned int id )
|
||||||
|
{
|
||||||
|
this->configID = id;
|
||||||
|
this->loadConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::setConfig( const ::std::string &id )
|
||||||
|
{
|
||||||
|
map<string, unsigned int>::const_iterator ref = PrivateStatic::blueprintIndex.find( ::Utility::String::toLowerCase(string(id)) );
|
||||||
|
if( ref != PrivateStatic::blueprintIndex.end() )
|
||||||
|
{
|
||||||
|
this->configID = ref->second;
|
||||||
|
this->loadConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::loadConfig( )
|
||||||
|
{
|
||||||
|
if( this->configID != Object::invalidID )
|
||||||
|
this->loadConfig( *PrivateStatic::blueprint[this->configID] );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::setPhysicsID( const CollisionHandler<Object>::Reference &id )
|
||||||
|
{ this->physicsID = id; }
|
||||||
|
|
||||||
|
void Object::setMass( const Float &mass )
|
||||||
|
{ this->mass = mass; }
|
||||||
|
|
||||||
|
void Object::setCenterOfMass( const Float3 &localPos )
|
||||||
|
{ this->rotationPivot = localPos; }
|
||||||
|
|
||||||
|
void Object::setScaling( const ::Oyster::Math::Float3 &scaleL )
|
||||||
|
{
|
||||||
|
this->body.boundingOffset.x /= this->scaling.x;
|
||||||
|
this->body.boundingOffset.y /= this->scaling.y;
|
||||||
|
this->body.boundingOffset.z /= this->scaling.z;
|
||||||
|
this->body.boundingOffset *= scaleL;
|
||||||
|
|
||||||
|
if( this->physicsID != CollisionHandler<Object>::Reference::invalid )
|
||||||
|
this->physicsID.setBoundaryReach( this->body.boundingOffset.length() );
|
||||||
|
|
||||||
|
this->scaling = scaleL;
|
||||||
|
this->worldIsOutOfDate = this->viewIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::applyForceL( const Float3 &localForce, const Float3 &localPos )
|
||||||
|
{ MoveAble::accelerate( localForce / this->mass, localPos ); }
|
||||||
|
|
||||||
|
void Object::applyForceW( const Float3 &worldForce, const Float3 &worldPos )
|
||||||
|
{
|
||||||
|
Float4 localForce, localPos;
|
||||||
|
transformVector( localForce, Float4(worldForce, 0.0f), this->getViewNormalMatrix() );
|
||||||
|
transformVector( localPos, Float4(worldPos, 1.0f), this->getViewPointMatrix() );
|
||||||
|
|
||||||
|
MoveAble::accelerate( localForce.xyz / this->mass, localPos.xyz );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::moveToLimbo( )
|
||||||
|
{
|
||||||
|
Float4x4 m = this->getOrientation();
|
||||||
|
m.v[0]=m.v[1]=m.v[2]=m.v[3] = Float4::null;
|
||||||
|
this->setOrientation(m);
|
||||||
|
this->stop();
|
||||||
|
this->physicsID.moveToLimbo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::releaseFromLimbo( )
|
||||||
|
{
|
||||||
|
this->physicsID.leaveLimbo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::update( )
|
||||||
|
{
|
||||||
|
// Speed Control
|
||||||
|
Float speedSquared = this->speed.dot( this->speed );
|
||||||
|
|
||||||
|
if( speedSquared > ( this->movementProperty.maxSpeed * this->movementProperty.maxSpeed ) )
|
||||||
|
{ // drop the speed to max and kill acceleration this update
|
||||||
|
this->speed *= ( this->movementProperty.maxSpeed / ::std::sqrt(speedSquared) );
|
||||||
|
//this->acceleration = Float3::null;
|
||||||
|
}
|
||||||
|
if( this->disableReduceMovementCount == 0 )
|
||||||
|
{ // kill movement if moving slow enough, or deAccelerate
|
||||||
|
Float deAccelerate = this->movementProperty.deAcceleration * MoveAble::getDiscreteTimeSlice();
|
||||||
|
|
||||||
|
if( speedSquared <= ( deAccelerate * deAccelerate ) )
|
||||||
|
this->speed = Float3::null;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
speedSquared = ::std::sqrt(speedSquared);
|
||||||
|
this->speed *= (speedSquared - deAccelerate) / speedSquared;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotation Control
|
||||||
|
speedSquared = this->rotationalSpeed.dot( this->rotationalSpeed );
|
||||||
|
|
||||||
|
if( speedSquared > ( this->rotationProperty.maxSpeed * this->rotationProperty.maxSpeed ) )
|
||||||
|
{ // drop the rotationSpeed to max and kill acceleration this update
|
||||||
|
this->rotationalSpeed *= ( this->rotationProperty.maxSpeed / ::std::sqrt(speedSquared) );
|
||||||
|
this->rotationalAcceleration = Float3::null;
|
||||||
|
}
|
||||||
|
if( this->disableReduceRotationCount == 0 )
|
||||||
|
{ // kill rotation if moving slow enough, or deAccelerate
|
||||||
|
Float deAccelerate = this->rotationProperty.deAcceleration * MoveAble::getDiscreteTimeSlice();
|
||||||
|
|
||||||
|
if( speedSquared <= ( deAccelerate * deAccelerate ) )
|
||||||
|
this->rotationalSpeed = Float3::null;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
speedSquared = ::std::sqrt(speedSquared);
|
||||||
|
this->rotationalSpeed *= (speedSquared - deAccelerate) / speedSquared;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MoveAble::update();
|
||||||
|
if( this->physicsID != CollisionHandler<Object>::Reference::invalid )
|
||||||
|
this->physicsID.setPosition( this->body.orientation.v[3].xyz );
|
||||||
|
this->worldIsOutOfDate = this->viewIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::pitchUp( )
|
||||||
|
{ this->accelerateTurn( this->body.orientation.v[0].xyz * -this->rotationProperty.acceleration.pitch ); }
|
||||||
|
|
||||||
|
void Object::pitchDown( )
|
||||||
|
{ this->accelerateTurn( this->body.orientation.v[0].xyz * this->rotationProperty.acceleration.pitch ); }
|
||||||
|
|
||||||
|
void Object::yawLeft( )
|
||||||
|
{ this->accelerateTurn( this->body.orientation.v[1].xyz * -this->rotationProperty.acceleration.yaw ); }
|
||||||
|
|
||||||
|
void Object::yawRight( )
|
||||||
|
{ this->accelerateTurn( this->body.orientation.v[1].xyz * this->rotationProperty.acceleration.yaw ); }
|
||||||
|
|
||||||
|
void Object::rollLeft( )
|
||||||
|
{ this->accelerateTurn( this->body.orientation.v[2].xyz * this->rotationProperty.acceleration.roll ); }
|
||||||
|
|
||||||
|
void Object::rollRight( )
|
||||||
|
{ this->accelerateTurn( this->body.orientation.v[2].xyz * -this->rotationProperty.acceleration.roll ); }
|
||||||
|
|
||||||
|
void Object::thrustForward( )
|
||||||
|
{ this->accelerate( this->body.orientation.v[2].xyz * this->movementProperty.acceleration.forward ); }
|
||||||
|
|
||||||
|
void Object::thrustBackward( )
|
||||||
|
{ this->accelerate( this->body.orientation.v[2].xyz * -this->movementProperty.acceleration.backward ); }
|
||||||
|
|
||||||
|
void Object::strafeLeft( )
|
||||||
|
{ this->accelerate( this->body.orientation.v[0].xyz * -this->movementProperty.acceleration.horizontal ); }
|
||||||
|
|
||||||
|
void Object::strafeRight( )
|
||||||
|
{ this->accelerate( this->body.orientation.v[0].xyz * this->movementProperty.acceleration.horizontal ); }
|
||||||
|
|
||||||
|
void Object::climb( )
|
||||||
|
{ this->accelerate( this->body.orientation.v[1].xyz * this->movementProperty.acceleration.vertical ); }
|
||||||
|
|
||||||
|
void Object::dive( )
|
||||||
|
{ this->accelerate( this->body.orientation.v[1].xyz * -this->movementProperty.acceleration.vertical ); }
|
||||||
|
|
||||||
|
void Object::disableMovementReduction( )
|
||||||
|
{ ++this->disableReduceMovementCount; }
|
||||||
|
|
||||||
|
void Object::enableMovementReduction( bool forceIt )
|
||||||
|
{
|
||||||
|
if( forceIt )
|
||||||
|
this->disableReduceMovementCount = 0;
|
||||||
|
else if( --this->disableReduceMovementCount < 0) this->disableReduceMovementCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::disableRotationReduction( )
|
||||||
|
{ ++this->disableReduceRotationCount; }
|
||||||
|
|
||||||
|
void Object::enableRotationReduction( bool forceIt )
|
||||||
|
{
|
||||||
|
if( forceIt )
|
||||||
|
this->disableReduceRotationCount = 0;
|
||||||
|
else if( --this->disableReduceRotationCount < 0) this->disableReduceRotationCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object::Result Object::writeToKeyFrame( KeyFrame &buffer ) const
|
||||||
|
{
|
||||||
|
if( buffer.numObjects < (signed)::Utility::StaticArray::numElementsOf( buffer.Objects ) )
|
||||||
|
{
|
||||||
|
buffer.Objects[buffer.numObjects].id = this->objectID;
|
||||||
|
buffer.Objects[buffer.numObjects].TypeId = this->configID;
|
||||||
|
buffer.Objects[buffer.numObjects].RotationVec = this->rotationalSpeed;
|
||||||
|
buffer.Objects[buffer.numObjects].MoveVec = this->speed;
|
||||||
|
|
||||||
|
//TODO: edit to world when they are avaliable
|
||||||
|
buffer.Objects[buffer.numObjects].World = this->body.orientation;
|
||||||
|
|
||||||
|
//buffer.Objects[buffer.numObjects].ForwardVec = this->body.orientation.v[2].xyz;
|
||||||
|
//buffer.Objects[buffer.numObjects].UpVec = this->body.orientation.v[1].xyz;
|
||||||
|
|
||||||
|
++buffer.numObjects;
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
return Failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Float4x4 & Object::getWorldPointMatrix( ) const
|
||||||
|
{
|
||||||
|
if( this->worldIsOutOfDate )
|
||||||
|
{
|
||||||
|
transformMatrix( this->world,
|
||||||
|
Float4x4( Float4::standardUnitX * this->scaling.x,
|
||||||
|
Float4::standardUnitY * this->scaling.y,
|
||||||
|
Float4::standardUnitZ * this->scaling.z,
|
||||||
|
Float4::standardUnitW ),
|
||||||
|
this->body.orientation );
|
||||||
|
this->worldIsOutOfDate = false;
|
||||||
|
}
|
||||||
|
return this->world;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Float4x4 & Object::getViewPointMatrix( ) const
|
||||||
|
{
|
||||||
|
if( this->viewIsOutOfDate )
|
||||||
|
{
|
||||||
|
this->view = this->getWorldPointMatrix().getInverse();
|
||||||
|
this->viewIsOutOfDate = false;
|
||||||
|
}
|
||||||
|
return this->view;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::setOrientation( const Float4x4 & orientation )
|
||||||
|
{
|
||||||
|
MoveAble::setOrientation( orientation );
|
||||||
|
if( this->physicsID != CollisionHandler<Object>::Reference::invalid )
|
||||||
|
this->physicsID.setPosition( orientation.v[3].xyz );
|
||||||
|
this->worldIsOutOfDate = this->viewIsOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const InstanceBlueprint & Object::getConfigData( unsigned int configID )
|
||||||
|
{ return *PrivateStatic::blueprint[configID]; }
|
||||||
|
|
||||||
|
void Object::loadConfig( const InstanceBlueprint &config )
|
||||||
|
{
|
||||||
|
this->mass = (Float)config.mass;
|
||||||
|
this->setCenterOfMass( config.centerOfMass );
|
||||||
|
this->body.boundingOffset = ::Utility::Value::abs( config.hitBox.position ) + config.hitBox.halfSize;
|
||||||
|
|
||||||
|
this->movementProperty.maxSpeed = config.movementProperty.maxSpeed;
|
||||||
|
this->movementProperty.deAcceleration = config.movementProperty.deAcceleration;
|
||||||
|
this->movementProperty.acceleration.forward = config.movementProperty.acceleration.forward;
|
||||||
|
this->movementProperty.acceleration.backward = config.movementProperty.acceleration.backward;
|
||||||
|
this->movementProperty.acceleration.horizontal = config.movementProperty.acceleration.horizontal;
|
||||||
|
this->movementProperty.acceleration.vertical = config.movementProperty.acceleration.vertical;
|
||||||
|
|
||||||
|
this->rotationProperty.maxSpeed = config.rotationProperty.maxSpeed;
|
||||||
|
this->rotationProperty.deAcceleration = config.rotationProperty.deAcceleration;
|
||||||
|
this->rotationProperty.acceleration.pitch = config.rotationProperty.acceleration.pitch;
|
||||||
|
this->rotationProperty.acceleration.yaw = config.rotationProperty.acceleration.yaw;
|
||||||
|
this->rotationProperty.acceleration.roll = config.rotationProperty.acceleration.roll;
|
||||||
|
|
||||||
|
if( this->physicsID != CollisionHandler<Object>::Reference::invalid )
|
||||||
|
this->physicsID.setBoundaryReach( this->body.boundingOffset.length() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Oyster { namespace Game
|
||||||
|
{
|
||||||
|
template <>
|
||||||
|
bool CollisionHandler<::GameLogic::Object>::simpleCollisionConfirmation( const typename ::GameLogic::Object &entity, const ::Oyster::Collision::ICollideable *sampler )
|
||||||
|
{ return sampler->Intersects( &entity.getCollisionBox() ); }
|
||||||
|
} }
|
|
@ -0,0 +1,147 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef GAME_OBJECT_H
|
||||||
|
#define GAME_OBJECT_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "OysterCollision.h"
|
||||||
|
#include "OysterGame.h"
|
||||||
|
#include "Protocoll.h"
|
||||||
|
#include "InstanceBlueprint.h"
|
||||||
|
|
||||||
|
namespace GameLogic
|
||||||
|
{
|
||||||
|
class Object : public ::Oyster::Game::MoveAble
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Result { Success, Failure };
|
||||||
|
enum Type { Player = 0, Static = 1, Destructable = 3, Undefined = 4 };
|
||||||
|
static Result init( const ::std::string &iniFile ); // needed anymore?
|
||||||
|
static Result importEntities( ::std::vector<unsigned int> &outputConfigID, const ::std::string &entityFile, const ::Oyster::Math::Float4x4 &transform = ::Oyster::Math::Float4x4::identity );
|
||||||
|
static void clearEntityresources( );
|
||||||
|
static unsigned int getNumObjectsCreated( );
|
||||||
|
static const InstanceBlueprint &getConfig( unsigned int id );
|
||||||
|
static const InstanceBlueprint &getConfig( const ::std::string &handle );
|
||||||
|
|
||||||
|
static void onCollisionAction( Object *visitor, Object *hitEntity );
|
||||||
|
|
||||||
|
static const unsigned int invalidID;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
::Oyster::Math::Float maxSpeed, deAcceleration;
|
||||||
|
struct{ ::Oyster::Math::Float forward, backward, horizontal, vertical; } acceleration;
|
||||||
|
} movementProperty;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
::Oyster::Math::Float maxSpeed, deAcceleration;
|
||||||
|
struct{ ::Oyster::Math::Float pitch, yaw, roll; } acceleration;
|
||||||
|
} rotationProperty;
|
||||||
|
|
||||||
|
Object( );
|
||||||
|
Object( const Object &object );
|
||||||
|
Object( const ::Oyster::Math::Float4x4 &orientation, const ::Oyster::Math::Float3 ¢erOfMass = ::Oyster::Math::Float3::null );
|
||||||
|
Object( const ::Oyster::Collision::Box &body, const ::Oyster::Math::Float3 ¢erOfMass = ::Oyster::Math::Float3::null );
|
||||||
|
virtual ~Object( );
|
||||||
|
|
||||||
|
Object & operator = ( const Object &object );
|
||||||
|
virtual Object * clone( ) const;
|
||||||
|
|
||||||
|
virtual Type getType( ) const;
|
||||||
|
const unsigned int & getObjectID( ) const;
|
||||||
|
const unsigned int & getConfigID( ) const;
|
||||||
|
const ::Oyster::Game::CollisionHandler<Object>::Reference & getPhysicsID( ) const;
|
||||||
|
const ::Oyster::Math::Float & getMass( ) const;
|
||||||
|
const ::Oyster::Math::Float3 & getCenterOfMass( ) const;
|
||||||
|
::Oyster::Math::Float3 getInertia( const ::Oyster::Math::Float3 &offset ) const;
|
||||||
|
const ::Oyster::Collision::Box & getCollisionBox( ) const;
|
||||||
|
bool isActive( ) const;
|
||||||
|
|
||||||
|
void setConfig( unsigned int id );
|
||||||
|
void setConfig( const ::std::string &id );
|
||||||
|
void loadConfig( );
|
||||||
|
|
||||||
|
void setPhysicsID( const ::Oyster::Game::CollisionHandler<Object>::Reference &id );
|
||||||
|
void setMass( const ::Oyster::Math::Float &mass );
|
||||||
|
void setCenterOfMass( const ::Oyster::Math::Float3 &localPos );
|
||||||
|
void setScaling( const ::Oyster::Math::Float3 &scaleL );
|
||||||
|
|
||||||
|
void applyForceL( const ::Oyster::Math::Float3 &localForce, const ::Oyster::Math::Float3 &localPos );
|
||||||
|
void applyForceW( const ::Oyster::Math::Float3 &worldForce, const ::Oyster::Math::Float3 &worldPos );
|
||||||
|
virtual void applyDamage( unsigned char magnitude, Object &attacker ) {}
|
||||||
|
virtual void applyHeal( unsigned char magnitude ) {}
|
||||||
|
virtual void HealShield( unsigned char magnitude ) {}
|
||||||
|
virtual void DamageShield( unsigned char magnitude ) {}
|
||||||
|
virtual void onDeath( Object &killer ) {}
|
||||||
|
virtual void onKill( Object &victim ) {}
|
||||||
|
|
||||||
|
void moveToLimbo( );
|
||||||
|
void releaseFromLimbo( );
|
||||||
|
|
||||||
|
virtual void update( );
|
||||||
|
|
||||||
|
virtual void firePrimaryWeapon( ) {}
|
||||||
|
virtual void fireSecondaryWeapon( ) {}
|
||||||
|
virtual void fireSpecial( ) {}
|
||||||
|
virtual void lockTarget( unsigned int objectID ) {}
|
||||||
|
|
||||||
|
inline void activateMovementStabilisator( ) { this->enableMovementReduction( true ); }
|
||||||
|
inline void deactivateMovementStabilisator( ) { this->disableMovementReduction(); }
|
||||||
|
|
||||||
|
void pitchUp( );
|
||||||
|
void pitchDown( );
|
||||||
|
void yawLeft( );
|
||||||
|
void yawRight( );
|
||||||
|
void rollLeft( );
|
||||||
|
void rollRight( );
|
||||||
|
|
||||||
|
void thrustForward( );
|
||||||
|
void thrustBackward( );
|
||||||
|
void strafeLeft( );
|
||||||
|
void strafeRight( );
|
||||||
|
void climb( );
|
||||||
|
void dive( );
|
||||||
|
|
||||||
|
void disableMovementReduction( );
|
||||||
|
void enableMovementReduction( bool forceIt = false );
|
||||||
|
|
||||||
|
void disableRotationReduction( );
|
||||||
|
void enableRotationReduction( bool forceIt = false );
|
||||||
|
|
||||||
|
virtual Result writeToKeyFrame( KeyFrame &buffer ) const;
|
||||||
|
|
||||||
|
|
||||||
|
const ::Oyster::Math::Float4x4 & getWorldPointMatrix( ) const;
|
||||||
|
const ::Oyster::Math::Float4x4 & getViewPointMatrix( ) const;
|
||||||
|
inline ::Oyster::Math::Float4x4 getWorldNormalMatrix( ) const { return this->getViewPointMatrix().getTranspose(); }
|
||||||
|
inline ::Oyster::Math::Float4x4 getViewNormalMatrix( ) const { return this->getWorldPointMatrix().getTranspose(); }
|
||||||
|
virtual void setOrientation( const ::Oyster::Math::Float4x4 & orientation );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static const InstanceBlueprint & getConfigData( unsigned int configID );
|
||||||
|
|
||||||
|
virtual void loadConfig( const InstanceBlueprint &config );
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int objectID, configID;
|
||||||
|
::Oyster::Game::CollisionHandler<Object>::Reference physicsID;
|
||||||
|
::Oyster::Math::Float mass;
|
||||||
|
int disableReduceMovementCount, disableReduceRotationCount;
|
||||||
|
|
||||||
|
::Oyster::Math::Float3 scaling;
|
||||||
|
mutable ::Oyster::Math::Float4x4 view, world; mutable bool viewIsOutOfDate, worldIsOutOfDate;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Oyster { namespace Game
|
||||||
|
{
|
||||||
|
template <>
|
||||||
|
bool CollisionHandler<::GameLogic::Object>::simpleCollisionConfirmation( const typename ::GameLogic::Object &entity, const ::Oyster::Collision::ICollideable *sampler );
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,241 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "Player.h"
|
||||||
|
#include "Session.h"
|
||||||
|
#include "GameLUA.h"
|
||||||
|
|
||||||
|
#include <iostream> // TODO: to be removed
|
||||||
|
|
||||||
|
using namespace ::GameLogic;
|
||||||
|
using namespace ::Oyster::Math;
|
||||||
|
using namespace ::Oyster::Collision;
|
||||||
|
using ::std::string;
|
||||||
|
|
||||||
|
const unsigned char Player::noTeam = 255;
|
||||||
|
|
||||||
|
Player::Player( ) : Object(), session(NULL), name(), playerID(-1), teamID(Player::noTeam), killCount(0), teamKillCount(0), deathCount(0), lockedTarget(NULL), hullPoints(255), shieldPoints(0), specialID(255), primaryWeapon(Weapon::Test), primaryWeaponCooldown(0.0f) {}
|
||||||
|
Player::Player( const Player &player ) : Object(player), session(player.session), name(player.name), playerID(player.playerID), teamID(player.teamID), killCount(player.killCount), teamKillCount(player.teamKillCount), deathCount(player.deathCount), lockedTarget(player.lockedTarget), hullPoints(player.hullPoints), shieldPoints(player.shieldPoints), specialID(player.specialID), primaryWeapon(player.primaryWeapon), primaryWeaponCooldown(player.primaryWeaponCooldown) {}
|
||||||
|
Player::Player( const Float4x4 &orientation, const Float3 ¢erOfMass ) : Object(orientation, centerOfMass), session(NULL), name(), playerID(-1), teamID(Player::noTeam), killCount(0), teamKillCount(0), deathCount(0), lockedTarget(NULL), hullPoints(255), shieldPoints(0), specialID(255), primaryWeapon(Weapon::Test), primaryWeaponCooldown(0.0f) {}
|
||||||
|
Player::Player( const Box &body, const Float3 ¢erOfMass ) : Object(body, centerOfMass), session(NULL), name(), playerID(-1), teamID(Player::noTeam), killCount(0), teamKillCount(0), deathCount(0), lockedTarget(NULL), hullPoints(255), shieldPoints(0), specialID(255), primaryWeapon(Weapon::Test), primaryWeaponCooldown(0.0f) {}
|
||||||
|
Player::~Player( ) {}
|
||||||
|
|
||||||
|
Player & Player::operator = ( const Player &player )
|
||||||
|
{
|
||||||
|
Object::operator=( player );
|
||||||
|
this->session = player.session;
|
||||||
|
this->name = player.name;
|
||||||
|
this->playerID = player.playerID;
|
||||||
|
this->teamID = player.teamID;
|
||||||
|
this->killCount = player.killCount;
|
||||||
|
this->teamKillCount = player.teamKillCount;
|
||||||
|
this->deathCount = player.deathCount;
|
||||||
|
this->hullPoints = player.hullPoints;
|
||||||
|
this->shieldPoints = player.shieldPoints;
|
||||||
|
this->specialID = player.specialID;
|
||||||
|
this->primaryWeapon = player.primaryWeapon;
|
||||||
|
this->primaryWeaponCooldown = player.primaryWeaponCooldown;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object * Player::clone( ) const
|
||||||
|
{ return new Player(*this); }
|
||||||
|
|
||||||
|
void Player::update( float deltaTime )
|
||||||
|
{
|
||||||
|
Object::update( );
|
||||||
|
|
||||||
|
if (primaryWeaponCooldown > 0.0f)
|
||||||
|
primaryWeaponCooldown -= deltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::firePrimaryWeapon( )
|
||||||
|
{
|
||||||
|
if (primaryWeaponCooldown <= 0.0f)
|
||||||
|
GameLUA::executeOnFireScript( primaryWeapon, *this );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::fireSecondaryWeapon( )
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::fireSpecial( )
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::lockTarget( unsigned int objectID )
|
||||||
|
{ this->lockedTarget = this->session->objectIDLib[objectID]; }
|
||||||
|
|
||||||
|
void Player::setPrimaryWeapon(Weapon::Type weapon)
|
||||||
|
{
|
||||||
|
primaryWeapon = weapon;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::setPrimaryWeaponCooldown(float cooldown)
|
||||||
|
{
|
||||||
|
primaryWeaponCooldown = cooldown;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object::Type Player::getType( ) const
|
||||||
|
{ return Object::Player; }
|
||||||
|
|
||||||
|
const string & Player::getName( ) const
|
||||||
|
{ return this->name; }
|
||||||
|
|
||||||
|
int Player::getPlayerID( ) const
|
||||||
|
{
|
||||||
|
return this->playerID;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char Player::getTeamID( ) const
|
||||||
|
{ return this->teamID; }
|
||||||
|
|
||||||
|
unsigned int Player::getNumKills( ) const
|
||||||
|
{ return this->killCount; }
|
||||||
|
|
||||||
|
unsigned int Player::getNumTeamKills( ) const
|
||||||
|
{ return this->teamKillCount; }
|
||||||
|
|
||||||
|
unsigned int Player::getNumDeaths( ) const
|
||||||
|
{ return this->deathCount; }
|
||||||
|
|
||||||
|
Session *Player::getSession( ) const
|
||||||
|
{ return this->session; }
|
||||||
|
|
||||||
|
unsigned char Player::getHullPoints( ) const
|
||||||
|
{ return this->hullPoints; }
|
||||||
|
|
||||||
|
unsigned char Player::getShieldPoints( ) const
|
||||||
|
{ return this->shieldPoints; }
|
||||||
|
|
||||||
|
void Player::setName( const string &name )
|
||||||
|
{ this->name = name; }
|
||||||
|
|
||||||
|
void Player::setPlayerID( int id )
|
||||||
|
{
|
||||||
|
playerID = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::setTeam( unsigned char teamID )
|
||||||
|
{ this->teamID = teamID; }
|
||||||
|
|
||||||
|
void Player::setHullPoints( unsigned char value )
|
||||||
|
{
|
||||||
|
this->hullPoints = value;
|
||||||
|
|
||||||
|
if( value == 0 )
|
||||||
|
this->onDeath( *this );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::setShieldPoints( unsigned char value )
|
||||||
|
{ this->shieldPoints = value; }
|
||||||
|
|
||||||
|
void Player::resetScores( )
|
||||||
|
{ this->killCount = this->teamKillCount = this->deathCount = 0; }
|
||||||
|
|
||||||
|
void Player::applyDamage( unsigned char magnitude, Object &attacker )
|
||||||
|
{
|
||||||
|
if( this->shieldPoints > 0 )
|
||||||
|
{
|
||||||
|
magnitude = (unsigned char)(unsigned int)((float)magnitude * ( (float)this->shieldPoints / (float)this->getConfigData( this->getConfigID() ).shieldPoints ));
|
||||||
|
|
||||||
|
if( magnitude == 0 )
|
||||||
|
magnitude = 1;
|
||||||
|
|
||||||
|
if( this->shieldPoints >= magnitude )
|
||||||
|
{
|
||||||
|
this->shieldPoints -= magnitude;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
magnitude -= this->shieldPoints;
|
||||||
|
this->shieldPoints = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( this->hullPoints <= magnitude )
|
||||||
|
{
|
||||||
|
this->hullPoints = 0;
|
||||||
|
this->onDeath( attacker );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
this->hullPoints -= magnitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::applyHeal( unsigned char magnitude )
|
||||||
|
{
|
||||||
|
this->hullPoints += magnitude;
|
||||||
|
|
||||||
|
unsigned int id = this->getConfigID();
|
||||||
|
if( id != Object::invalidID )
|
||||||
|
this->hullPoints = ::Utility::Value::min( this->hullPoints, (unsigned char)this->getConfigData(id).hullPoints );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::onDeath( Object &killer )
|
||||||
|
{
|
||||||
|
killer.onKill( *this );
|
||||||
|
++this->deathCount;
|
||||||
|
Player* p = dynamic_cast<Player*>(&killer);
|
||||||
|
Event::ShipDestroyed* e = new Event::ShipDestroyed(this->playerID,p->playerID);
|
||||||
|
for(int i=0;i < PLAYER_MAX_COUNT; ++i)
|
||||||
|
{
|
||||||
|
e->setScore(i,this->session->player[i].killCount, this->session->player[i].deathCount, this->session->player[i].teamKillCount);
|
||||||
|
}
|
||||||
|
this->session->eventList.push_back(e);
|
||||||
|
|
||||||
|
this->moveToLimbo();
|
||||||
|
|
||||||
|
this->spawn();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::onKill( Object &victim )
|
||||||
|
{
|
||||||
|
if( victim.getType() == Object::Player )
|
||||||
|
{
|
||||||
|
Player *v = (Player*)&victim;
|
||||||
|
if( this->teamID == Player::noTeam || this->teamID != v->teamID )
|
||||||
|
++this->killCount;
|
||||||
|
else
|
||||||
|
++this->teamKillCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::spawn( )
|
||||||
|
{
|
||||||
|
int num = (int)this->session->spawnPoint.size();
|
||||||
|
this->stop();
|
||||||
|
|
||||||
|
if( num > 0 )
|
||||||
|
{
|
||||||
|
int spawnRef = rand() % (int)num;
|
||||||
|
Box spawnZone = this->body;
|
||||||
|
unsigned int channel = (unsigned int)Object::Player;
|
||||||
|
|
||||||
|
for( int i = 0; i < num; ++i )
|
||||||
|
{
|
||||||
|
spawnZone.orientation = this->session->spawnPoint[spawnRef];
|
||||||
|
if( this->session->world.collidesWithSomething(&channel, 1, &spawnZone) )
|
||||||
|
spawnRef = (spawnRef + 1) % (int)num;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->setOrientation( spawnZone.orientation );
|
||||||
|
this->setConfig(this->getConfigID());
|
||||||
|
this->releaseFromLimbo();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->moveToLimbo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::loadConfig( const InstanceBlueprint &config )
|
||||||
|
{
|
||||||
|
Object::loadConfig( config );
|
||||||
|
this->hullPoints = config.hullPoints;
|
||||||
|
this->shieldPoints = config.shieldPoints;
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef GAMELOGIC_PLAYER_H
|
||||||
|
#define GAMELOGIC_PLAYER_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "Object.h"
|
||||||
|
#include "Weapon.h"
|
||||||
|
|
||||||
|
namespace GameLogic
|
||||||
|
{
|
||||||
|
class Session;
|
||||||
|
|
||||||
|
class Player : public Object
|
||||||
|
{
|
||||||
|
friend class Session;
|
||||||
|
public:
|
||||||
|
enum State { Vacant, Active, Dead, Limbo };
|
||||||
|
static const unsigned char noTeam;
|
||||||
|
|
||||||
|
Player( );
|
||||||
|
Player( const Player &player );
|
||||||
|
Player( const ::Oyster::Math::Float4x4 &orientation, const ::Oyster::Math::Float3 ¢erOfMass = ::Oyster::Math::Float3::null );
|
||||||
|
Player( const ::Oyster::Collision::Box &body, const ::Oyster::Math::Float3 ¢erOfMass = ::Oyster::Math::Float3::null );
|
||||||
|
virtual ~Player( );
|
||||||
|
|
||||||
|
Player & operator = ( const Player &player );
|
||||||
|
virtual Object * clone( ) const;
|
||||||
|
|
||||||
|
virtual void update( float deltaTime );
|
||||||
|
|
||||||
|
virtual void firePrimaryWeapon( );
|
||||||
|
virtual void fireSecondaryWeapon( );
|
||||||
|
virtual void fireSpecial( );
|
||||||
|
virtual void lockTarget( unsigned int objectID );
|
||||||
|
void setPrimaryWeapon(Weapon::Type weapon);
|
||||||
|
void setPrimaryWeaponCooldown(float cooldown);
|
||||||
|
|
||||||
|
virtual Object::Type getType( ) const;
|
||||||
|
const ::std::string & getName( ) const;
|
||||||
|
int getPlayerID( ) const;
|
||||||
|
unsigned char getTeamID( ) const;
|
||||||
|
unsigned int getNumKills( ) const;
|
||||||
|
unsigned int getNumTeamKills( ) const;
|
||||||
|
unsigned int getNumDeaths( ) const;
|
||||||
|
Session *getSession( ) const;
|
||||||
|
unsigned char getHullPoints( ) const;
|
||||||
|
unsigned char getShieldPoints( ) const;
|
||||||
|
|
||||||
|
void setName( const ::std::string &name );
|
||||||
|
void setPlayerID( int id );
|
||||||
|
void setTeam( unsigned char teamID );
|
||||||
|
void setHullPoints( unsigned char value );
|
||||||
|
void setShieldPoints( unsigned char value );
|
||||||
|
void resetScores( );
|
||||||
|
|
||||||
|
virtual void applyDamage( unsigned char magnitude, Object &attacker );
|
||||||
|
virtual void applyHeal( unsigned char magnitude );
|
||||||
|
virtual void onDeath( Object &killer );
|
||||||
|
virtual void onKill( Object &victim );
|
||||||
|
|
||||||
|
// teleports a player to a random unblocked spawnpoint and release from Limbo. Will end up in limbo if unable to find a spawnpoint
|
||||||
|
void spawn( );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void loadConfig( const InstanceBlueprint &config );
|
||||||
|
|
||||||
|
private:
|
||||||
|
Session *session;
|
||||||
|
::std::string name;
|
||||||
|
int playerID;
|
||||||
|
unsigned int killCount, teamKillCount, deathCount;
|
||||||
|
const Object *lockedTarget;
|
||||||
|
unsigned char teamID, hullPoints, shieldPoints, specialID;
|
||||||
|
Weapon::Type primaryWeapon;
|
||||||
|
float primaryWeaponCooldown;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,320 @@
|
||||||
|
#include "Protocoll.h"
|
||||||
|
|
||||||
|
KeyFrame::KeyFrame()
|
||||||
|
{
|
||||||
|
numObjects=numParticles=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyFrame::KeyFrame(char* data)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int size= sizeof(int);
|
||||||
|
int* nums = &this->numObjects;
|
||||||
|
memcpy(&numObjects,data,size);
|
||||||
|
i+=size;
|
||||||
|
memcpy(&numParticles,data+i,size);
|
||||||
|
i+=size;
|
||||||
|
size=sizeof(Player);
|
||||||
|
|
||||||
|
memcpy(&Players,data+i,size*8);
|
||||||
|
i+=size*8;
|
||||||
|
|
||||||
|
size = sizeof(Object);
|
||||||
|
memcpy(&Objects,data+i,size*numObjects);
|
||||||
|
i+=size*numObjects;
|
||||||
|
|
||||||
|
size = sizeof(Effect);
|
||||||
|
memcpy(&Particle,&(data[i]),size*numParticles);
|
||||||
|
i+=size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int KeyFrame::GetSize()
|
||||||
|
{
|
||||||
|
int i=1;
|
||||||
|
i+=sizeof(int)*2;
|
||||||
|
i+=sizeof(Player)*8;
|
||||||
|
i+=sizeof(Object)*numObjects;
|
||||||
|
i+=sizeof(Effect)*numParticles;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyFrame::Pack(char * startPointer)
|
||||||
|
{
|
||||||
|
int i=0;
|
||||||
|
i+=sizeof(int)*2;
|
||||||
|
|
||||||
|
memcpy(startPointer,this,sizeof(int)*2);
|
||||||
|
memcpy(startPointer+i,this->Players,sizeof(Player)*8);
|
||||||
|
i+=sizeof(Player)*8;
|
||||||
|
memcpy(startPointer+i,this->Objects,sizeof(Object)*numObjects);
|
||||||
|
i+=sizeof(Object)*numObjects;
|
||||||
|
memcpy(startPointer+i,this->Particle,sizeof(Effect)*numParticles);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Protocol
|
||||||
|
{
|
||||||
|
using ::std::string;
|
||||||
|
using ::std::vector;
|
||||||
|
using ::std::map;
|
||||||
|
using ::Oyster::Math::Float4x4;
|
||||||
|
|
||||||
|
Mesh::Mesh( const string &_objFile ) : objFile(_objFile) {}
|
||||||
|
|
||||||
|
void Mesh::setObjFile( const string &fileName )
|
||||||
|
{ this->objFile = fileName; }
|
||||||
|
|
||||||
|
const string & Mesh::getObjFileName( ) const
|
||||||
|
{ return this->objFile; }
|
||||||
|
|
||||||
|
unsigned int Mesh::getRequiredBufferSize( ) const
|
||||||
|
{ return (unsigned int)(this->objFile.length() + 1); }
|
||||||
|
|
||||||
|
void Mesh::fillBuffer( void *targetBuffer ) const
|
||||||
|
{
|
||||||
|
char *buffer = (char*)targetBuffer;
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < this->objFile.length(); ++i )
|
||||||
|
buffer[i] = this->objFile[i];
|
||||||
|
buffer[this->objFile.length()] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh::readFromBuffer( const void *buffer )
|
||||||
|
{ this->objFile = (const char*)buffer; }
|
||||||
|
|
||||||
|
Object::Object( unsigned int _meshRef, const Float4x4 &_world )
|
||||||
|
: meshRef(_meshRef), world(_world) {}
|
||||||
|
|
||||||
|
void Object::setMeshRef( unsigned int ref )
|
||||||
|
{ this->meshRef = ref; }
|
||||||
|
|
||||||
|
void Object::setWorldMatrix( const Float4x4 &matrix )
|
||||||
|
{ this->world = matrix; }
|
||||||
|
|
||||||
|
unsigned int Object::getMeshRef( ) const
|
||||||
|
{ return this->meshRef; }
|
||||||
|
|
||||||
|
const Float4x4 & Object::getWorldMatrix( ) const
|
||||||
|
{ return this->world; }
|
||||||
|
|
||||||
|
unsigned int Object::getRequiredBufferSize( ) const
|
||||||
|
{ return (unsigned int)(sizeof(unsigned int) + sizeof(Float4x4)); }
|
||||||
|
|
||||||
|
void Object::fillBuffer( void *targetBuffer ) const
|
||||||
|
{
|
||||||
|
char *cBuffer = (char*)targetBuffer;
|
||||||
|
unsigned int *uiBuffer = (unsigned int*)targetBuffer;
|
||||||
|
|
||||||
|
uiBuffer[0] = this->meshRef;
|
||||||
|
|
||||||
|
cBuffer += sizeof(unsigned int);
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < sizeof(Float4x4); ++i )
|
||||||
|
cBuffer[i] = this->world.byte[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::readFromBuffer( const void *buffer )
|
||||||
|
{
|
||||||
|
const char *cBuffer = (const char*)buffer;
|
||||||
|
const unsigned int *uiBuffer = (const unsigned int*)buffer;
|
||||||
|
|
||||||
|
this->meshRef = uiBuffer[0];
|
||||||
|
|
||||||
|
cBuffer += sizeof(unsigned int);
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < sizeof(Float4x4); ++i )
|
||||||
|
this->world.byte[i] = cBuffer[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
MapRenderData::MapRenderData( )
|
||||||
|
: mesh(), object(), index()
|
||||||
|
{ this->requiredBufferSize = 2 * sizeof(unsigned int); }
|
||||||
|
|
||||||
|
void MapRenderData::clear( )
|
||||||
|
{
|
||||||
|
this->requiredBufferSize = 2 * sizeof(unsigned int);
|
||||||
|
this->mesh.clear();
|
||||||
|
this->object.clear();
|
||||||
|
this->index.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapRenderData::add( const Float4x4 &worldMatrix, const string &objFile )
|
||||||
|
{
|
||||||
|
unsigned int ref;
|
||||||
|
map<string, unsigned int>::const_iterator i = this->index.find( objFile );
|
||||||
|
if( i == this->index.end() )
|
||||||
|
{
|
||||||
|
ref = this->index[objFile] = (unsigned int)this->mesh.size();
|
||||||
|
this->mesh.push_back( Mesh(objFile) );
|
||||||
|
this->requiredBufferSize += this->mesh[ref].getRequiredBufferSize();
|
||||||
|
}
|
||||||
|
else ref = i->second;
|
||||||
|
|
||||||
|
this->object.push_back( Object(ref, worldMatrix) );
|
||||||
|
this->requiredBufferSize += this->object[this->object.size()-1].getRequiredBufferSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
const vector<Mesh> & MapRenderData::getMeshList( ) const
|
||||||
|
{ return this->mesh; }
|
||||||
|
|
||||||
|
const vector<Object> & MapRenderData::getObjectList( ) const
|
||||||
|
{ return this->object; }
|
||||||
|
|
||||||
|
unsigned int MapRenderData::getRequiredBufferSize( ) const
|
||||||
|
{ return this->requiredBufferSize; }
|
||||||
|
|
||||||
|
void MapRenderData::fillBuffer( void *targetBuffer ) const
|
||||||
|
{
|
||||||
|
unsigned int *uiBuffer = (unsigned int*)targetBuffer;
|
||||||
|
uiBuffer[0] = (unsigned int)this->mesh.size();
|
||||||
|
uiBuffer[1] = (unsigned int)this->object.size();
|
||||||
|
|
||||||
|
char *cBuffer = (char*)&uiBuffer[2];
|
||||||
|
|
||||||
|
for( vector<Mesh>::size_type i = 0; i < this->mesh.size(); ++i )
|
||||||
|
{
|
||||||
|
this->mesh[i].fillBuffer( cBuffer );
|
||||||
|
cBuffer += this->mesh[i].getRequiredBufferSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
for( vector<Object>::size_type i = 0; i < this->object.size(); ++i )
|
||||||
|
{
|
||||||
|
this->object[i].fillBuffer( cBuffer );
|
||||||
|
cBuffer += this->object[i].getRequiredBufferSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapRenderData::readFromBuffer( const void *buffer )
|
||||||
|
{
|
||||||
|
this->clear();
|
||||||
|
|
||||||
|
const unsigned int *uiBuffer = (const unsigned int*)buffer;
|
||||||
|
const char *cBuffer = (const char*)&uiBuffer[2];
|
||||||
|
|
||||||
|
this->mesh.reserve( uiBuffer[0] );
|
||||||
|
for( unsigned int i = 0; i < uiBuffer[0]; ++i )
|
||||||
|
{
|
||||||
|
vector<Mesh>::size_type ref = this->mesh.size();
|
||||||
|
this->mesh.push_back( Mesh() );
|
||||||
|
this->mesh[ref].readFromBuffer( cBuffer );
|
||||||
|
this->requiredBufferSize += this->mesh[ref].getRequiredBufferSize();
|
||||||
|
cBuffer += this->mesh[ref].getRequiredBufferSize();
|
||||||
|
|
||||||
|
this->index[this->mesh[ref].getObjFileName()] = (unsigned int)ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->object.reserve( uiBuffer[1] );
|
||||||
|
for( unsigned int i = 0; i < uiBuffer[1]; ++i )
|
||||||
|
{
|
||||||
|
vector<Object>::size_type ref = this->object.size();
|
||||||
|
this->object.push_back( Object() );
|
||||||
|
this->object[ref].readFromBuffer( cBuffer );
|
||||||
|
this->requiredBufferSize += this->object[ref].getRequiredBufferSize();
|
||||||
|
cBuffer += this->object[ref].getRequiredBufferSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PlayerRenderData::PlayerRenderData( )
|
||||||
|
: mesh(), playerMeshRef(), index()
|
||||||
|
{ this->requiredBufferSize = (unsigned int)(2 * sizeof(unsigned int)); }
|
||||||
|
|
||||||
|
void PlayerRenderData::clear( )
|
||||||
|
{
|
||||||
|
this->requiredBufferSize = (unsigned int)(2 * sizeof(unsigned int));
|
||||||
|
this->mesh.clear();
|
||||||
|
this->playerMeshRef.clear();
|
||||||
|
this->index.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerRenderData::addPlayer( const string &objFile )
|
||||||
|
{
|
||||||
|
unsigned int ref;
|
||||||
|
map<string, unsigned int>::const_iterator i = this->index.find( objFile );
|
||||||
|
if( i == this->index.end() )
|
||||||
|
{
|
||||||
|
ref = this->index[objFile] = (unsigned int)this->mesh.size();
|
||||||
|
this->mesh.push_back( Mesh(objFile) );
|
||||||
|
this->requiredBufferSize += this->mesh[ref].getRequiredBufferSize();
|
||||||
|
}
|
||||||
|
else ref = i->second;
|
||||||
|
|
||||||
|
this->playerMeshRef.push_back( ref );
|
||||||
|
this->requiredBufferSize += sizeof(unsigned int);
|
||||||
|
}
|
||||||
|
|
||||||
|
const vector<Mesh> & PlayerRenderData::getMeshList( ) const
|
||||||
|
{ return this->mesh; }
|
||||||
|
|
||||||
|
const vector<unsigned int> & PlayerRenderData::getPlayerMeshRefList( ) const
|
||||||
|
{ return this->playerMeshRef; }
|
||||||
|
|
||||||
|
unsigned int PlayerRenderData::getRequiredBufferSize( ) const
|
||||||
|
{ return this->requiredBufferSize; }
|
||||||
|
|
||||||
|
void PlayerRenderData::fillBuffer( void *targetBuffer ) const
|
||||||
|
{
|
||||||
|
unsigned int *uiBuffer = (unsigned int*)targetBuffer;
|
||||||
|
uiBuffer[0] = (unsigned int)this->mesh.size();
|
||||||
|
uiBuffer[1] = (unsigned int)this->playerMeshRef.size();
|
||||||
|
|
||||||
|
char *cBuffer = (char*)&uiBuffer[2];
|
||||||
|
|
||||||
|
for( vector<Mesh>::size_type i = 0; i < this->mesh.size(); ++i )
|
||||||
|
{
|
||||||
|
this->mesh[i].fillBuffer( cBuffer );
|
||||||
|
cBuffer += this->mesh[i].getRequiredBufferSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
uiBuffer = (unsigned int*)cBuffer;
|
||||||
|
for( vector<unsigned int>::size_type i = 0; i < this->playerMeshRef.size(); ++i )
|
||||||
|
{
|
||||||
|
*uiBuffer = this->playerMeshRef[i];
|
||||||
|
++uiBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerRenderData::readFromBuffer( const void *buffer )
|
||||||
|
{
|
||||||
|
this->clear();
|
||||||
|
|
||||||
|
const unsigned int *uiBuffer = (const unsigned int*)buffer;
|
||||||
|
const char *cBuffer = (const char*)&uiBuffer[2];
|
||||||
|
|
||||||
|
this->mesh.reserve( uiBuffer[0] );
|
||||||
|
for( unsigned int i = 0; i < uiBuffer[0]; ++i )
|
||||||
|
{
|
||||||
|
vector<Mesh>::size_type ref = this->mesh.size();
|
||||||
|
this->mesh.push_back( Mesh() );
|
||||||
|
this->mesh[ref].readFromBuffer( cBuffer );
|
||||||
|
this->requiredBufferSize += this->mesh[ref].getRequiredBufferSize();
|
||||||
|
cBuffer += this->mesh[ref].getRequiredBufferSize();
|
||||||
|
|
||||||
|
this->index[this->mesh[ref].getObjFileName()] = (unsigned int)ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned int *uiBuffer2 = (const unsigned int*)cBuffer;
|
||||||
|
for( unsigned int i = 0; i < uiBuffer[1]; ++i )
|
||||||
|
{
|
||||||
|
this->playerMeshRef.push_back( uiBuffer2[i] );
|
||||||
|
this->requiredBufferSize += sizeof(unsigned int);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderData::RenderData( ) : mapData(), playerData() {}
|
||||||
|
|
||||||
|
void RenderData::fillBuffer( void *targetBuffer ) const
|
||||||
|
{
|
||||||
|
char *cBuffer = (char*)targetBuffer;
|
||||||
|
this->mapData.fillBuffer( cBuffer );
|
||||||
|
cBuffer += this->mapData.getRequiredBufferSize();
|
||||||
|
this->playerData.fillBuffer( cBuffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderData::readFromBuffer( const void *buffer )
|
||||||
|
{
|
||||||
|
const char *cBuffer = (const char*)buffer;
|
||||||
|
this->mapData.readFromBuffer( cBuffer );
|
||||||
|
cBuffer += this->mapData.getRequiredBufferSize();
|
||||||
|
this->playerData.readFromBuffer( cBuffer );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,161 @@
|
||||||
|
#pragma once
|
||||||
|
#include "OysterMath.h"
|
||||||
|
|
||||||
|
using Oyster::Math::Float3;
|
||||||
|
|
||||||
|
struct KeyFrame
|
||||||
|
{
|
||||||
|
//header
|
||||||
|
//numobj cap?500
|
||||||
|
|
||||||
|
//per object
|
||||||
|
//id+rotationvec+movevec+ forwardvec+upvec+pos+typeID
|
||||||
|
|
||||||
|
//per particle
|
||||||
|
//pos1,pos2,EffectID
|
||||||
|
|
||||||
|
|
||||||
|
//per player
|
||||||
|
//hp, shield, specialAmmo?
|
||||||
|
int numObjects,numParticles;
|
||||||
|
|
||||||
|
struct Player
|
||||||
|
{
|
||||||
|
unsigned char Hp,Shield,Special;
|
||||||
|
}Players[8];
|
||||||
|
|
||||||
|
|
||||||
|
struct Object
|
||||||
|
{
|
||||||
|
unsigned int id, TypeId;
|
||||||
|
Float3 RotationVec;
|
||||||
|
Float3 MoveVec;
|
||||||
|
Oyster::Math::Float4x4 World;
|
||||||
|
}Objects[500];
|
||||||
|
|
||||||
|
struct Effect
|
||||||
|
{
|
||||||
|
Float3 Head,Tail;
|
||||||
|
int EffectType;
|
||||||
|
}Particle[160];
|
||||||
|
|
||||||
|
//return number of bytes from start to send over network
|
||||||
|
//set numofobjects
|
||||||
|
void Pack(char * startPointer);
|
||||||
|
|
||||||
|
int GetSize();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
KeyFrame();
|
||||||
|
|
||||||
|
//unpacks the char array as if it was a compressed keyframe
|
||||||
|
KeyFrame(char* data);
|
||||||
|
};
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include "OysterMath.h"
|
||||||
|
|
||||||
|
namespace Protocol
|
||||||
|
{
|
||||||
|
class Mesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mesh( const ::std::string &objFile = "" );
|
||||||
|
|
||||||
|
void setObjFile( const ::std::string &fileName );
|
||||||
|
|
||||||
|
const ::std::string & getObjFileName( ) const;
|
||||||
|
unsigned int getRequiredBufferSize( ) const;
|
||||||
|
|
||||||
|
void fillBuffer( void *targetBuffer ) const;
|
||||||
|
void readFromBuffer( const void *buffer );
|
||||||
|
|
||||||
|
private:
|
||||||
|
::std::string objFile;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Object( unsigned int meshRef = 0, const ::Oyster::Math::Float4x4 &world = ::Oyster::Math::Float4x4::identity );
|
||||||
|
|
||||||
|
void setMeshRef( unsigned int ref );
|
||||||
|
void setWorldMatrix( const ::Oyster::Math::Float4x4 &matrix );
|
||||||
|
|
||||||
|
unsigned int getMeshRef( ) const;
|
||||||
|
const ::Oyster::Math::Float4x4 & getWorldMatrix( ) const;
|
||||||
|
unsigned int getRequiredBufferSize( ) const;
|
||||||
|
|
||||||
|
void fillBuffer( void *targetBuffer ) const;
|
||||||
|
void readFromBuffer( const void *buffer );
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int meshRef;
|
||||||
|
::Oyster::Math::Float4x4 world;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MapRenderData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MapRenderData( );
|
||||||
|
|
||||||
|
void clear( );
|
||||||
|
void add( const ::Oyster::Math::Float4x4 &worldMatrix, const ::std::string &objFile );
|
||||||
|
|
||||||
|
const ::std::vector<Mesh> & getMeshList( ) const;
|
||||||
|
const ::std::vector<Object> & getObjectList( ) const;
|
||||||
|
unsigned int getRequiredBufferSize( ) const;
|
||||||
|
|
||||||
|
void fillBuffer( void *targetBuffer ) const;
|
||||||
|
void readFromBuffer( const void *buffer );
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int requiredBufferSize;
|
||||||
|
::std::vector<Mesh> mesh;
|
||||||
|
::std::vector<Object> object;
|
||||||
|
::std::map<::std::string, unsigned int> index;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PlayerRenderData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PlayerRenderData( );
|
||||||
|
|
||||||
|
void clear( );
|
||||||
|
void addPlayer( const ::std::string &objFile );
|
||||||
|
|
||||||
|
const ::std::vector<Mesh> & getMeshList( ) const;
|
||||||
|
const ::std::vector<unsigned int> & getPlayerMeshRefList( ) const;
|
||||||
|
unsigned int getRequiredBufferSize( ) const;
|
||||||
|
|
||||||
|
void fillBuffer( void *targetBuffer ) const;
|
||||||
|
void readFromBuffer( const void *buffer );
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int requiredBufferSize;
|
||||||
|
::std::vector<Mesh> mesh;
|
||||||
|
::std::vector<unsigned int> playerMeshRef;
|
||||||
|
::std::map<::std::string, unsigned int> index;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RenderData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MapRenderData mapData;
|
||||||
|
PlayerRenderData playerData;
|
||||||
|
|
||||||
|
RenderData( );
|
||||||
|
|
||||||
|
inline void RenderData::clear( )
|
||||||
|
{ this->mapData.clear(); this->playerData.clear(); }
|
||||||
|
|
||||||
|
inline unsigned int RenderData::getRequiredBufferSize( ) const
|
||||||
|
{ return this->mapData.getRequiredBufferSize() + this->playerData.getRequiredBufferSize(); }
|
||||||
|
|
||||||
|
void fillBuffer( void *targetBuffer ) const;
|
||||||
|
void readFromBuffer( const void *buffer );
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,576 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "Session.h"
|
||||||
|
#include "Bullet.h"
|
||||||
|
#include "GameLUA.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
/*
|
||||||
|
// BENCHMARK BLOCK
|
||||||
|
#include "WinTimer.h"
|
||||||
|
#include <iostream>
|
||||||
|
namespace Benchmark
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
double averageTime, totalTime, minTime, maxTime; unsigned int numSamples;
|
||||||
|
} timerData[10] = { 0.0f, 0.0f, ::std::numeric_limits<double>::max(), -::std::numeric_limits<double>::max(), 0 };
|
||||||
|
|
||||||
|
void sampleTime( const ::Utility::WinTimer &timer, unsigned char ref )
|
||||||
|
{
|
||||||
|
double elapsedTime = timer.getElapsedSeconds();
|
||||||
|
timerData[ref].totalTime += elapsedTime;
|
||||||
|
timerData[ref].minTime = ::Utility::Value::min( timerData[ref].minTime, elapsedTime );
|
||||||
|
timerData[ref].maxTime = ::Utility::Value::max( timerData[ref].maxTime, elapsedTime );
|
||||||
|
++timerData[ref].numSamples;
|
||||||
|
timerData[ref].averageTime = timerData[ref].totalTime / (double) timerData[ref].numSamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print( )
|
||||||
|
{
|
||||||
|
::std::ofstream file;
|
||||||
|
file.open( "BenchMarkData.txt", ::std::ios_base::app | ::std::ios_base::out );
|
||||||
|
|
||||||
|
if( file.is_open() )
|
||||||
|
{
|
||||||
|
file << "minTime\t\t: maxTime\t: averageTime\t\ttotalTime\tnumSamples\n";
|
||||||
|
for( unsigned char i = 0; i < 3; ++i )
|
||||||
|
file << timerData[i].minTime << (timerData[i].minTime == 0.0f ? "\t\t: " : "\t: ") << timerData[i].maxTime << "\t: " << timerData[i].averageTime << "\t\t" << timerData[i].totalTime << '\t' << timerData[i].numSamples <<'\n';
|
||||||
|
file << ::std::endl;
|
||||||
|
file.close();
|
||||||
|
::std::cout << "Benchmark data saved." << ::std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// END BENCHMARK BLOCK /**/
|
||||||
|
|
||||||
|
using namespace ::GameLogic;
|
||||||
|
using namespace ::Oyster::Math;
|
||||||
|
using namespace ::Oyster::Collision;
|
||||||
|
using namespace ::Oyster::Game;
|
||||||
|
using ::std::string;
|
||||||
|
using ::std::set;
|
||||||
|
using ::std::vector;
|
||||||
|
using ::std::ifstream;
|
||||||
|
using ::std::istream;
|
||||||
|
using ::std::stringstream;
|
||||||
|
|
||||||
|
namespace PrivateStatic
|
||||||
|
{
|
||||||
|
enum Channel { Player, Static };
|
||||||
|
|
||||||
|
inline Float3 getPositionOf( const Object &object )
|
||||||
|
{ return object.getOrientation().v[3].xyz; }
|
||||||
|
|
||||||
|
inline Float getPhysicalRangeOf( const Object &object )
|
||||||
|
{ return object.getSize().length() * 0.5f; }
|
||||||
|
|
||||||
|
inline Sphere getBubbleOf( const Object &object )
|
||||||
|
{ return Sphere( getPositionOf(object), getPhysicalRangeOf(object) ); }
|
||||||
|
|
||||||
|
void append( vector<unsigned int> &destination, const vector<unsigned int> &source )
|
||||||
|
{
|
||||||
|
for( vector<unsigned int>::size_type i = 0; i < source.size(); ++i )
|
||||||
|
destination.push_back( source[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
void readOrientation( Float4x4 &output, istream &stream, const Float4x4 &transform )
|
||||||
|
{
|
||||||
|
output = Float4x4::identity;
|
||||||
|
|
||||||
|
::Utility::Stream::readFloats( output.v[3], stream, 3 ); // position
|
||||||
|
::Utility::Stream::readFloats( output.v[2], stream, 3 ); // forward
|
||||||
|
::Utility::Stream::readFloats( output.v[1], stream, 3 ); // up
|
||||||
|
|
||||||
|
transformVector( output.v[3], output.v[3], transform ); // position
|
||||||
|
|
||||||
|
if( output.v[2].xyz != Float3::null && output.v[1].xyz != Float3::null )
|
||||||
|
{
|
||||||
|
// forward
|
||||||
|
transformVector( output.v[2], output.v[2], transform );
|
||||||
|
output.v[2].xyz.normalize();
|
||||||
|
|
||||||
|
// up
|
||||||
|
transformVector( output.v[1], output.v[1], transform );
|
||||||
|
output.v[1].xyz -= vectorProjection( output.v[1].xyz, output.v[2].xyz );
|
||||||
|
output.v[1].xyz.normalize();
|
||||||
|
|
||||||
|
// right
|
||||||
|
output.v[0].xyz = output.v[1].xyz.cross( output.v[2].xyz ).getNormalized();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output.v[0].xyz = Float3::standardUnitX;
|
||||||
|
output.v[1].xyz = Float3::standardUnitY;
|
||||||
|
output.v[2].xyz = Float3::standardUnitZ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Session::InitResult loadWorldFile( vector<Float4x4> &spawnPoints, vector<Object> &mapObjects, string &name, string &description, const string &fileName, const Float4x4 &transform )
|
||||||
|
{
|
||||||
|
spawnPoints.resize( 0 );
|
||||||
|
spawnPoints.reserve( 128 );
|
||||||
|
mapObjects.resize( 0 );
|
||||||
|
mapObjects.reserve( 1024 );
|
||||||
|
|
||||||
|
string workingDir;
|
||||||
|
::Utility::String::extractDirPath( workingDir, fileName, '\\' );
|
||||||
|
|
||||||
|
ifstream file( fileName );
|
||||||
|
if( file.is_open() )
|
||||||
|
{
|
||||||
|
string str;
|
||||||
|
vector<string> splitString;
|
||||||
|
stringstream subStream;
|
||||||
|
|
||||||
|
if( !file.eof() ) ::std::getline( file, name );
|
||||||
|
if( !file.eof() ) ::std::getline( file, str ); // gonna skip the handlername
|
||||||
|
if( !file.eof() )
|
||||||
|
{
|
||||||
|
::std::getline( file, description );
|
||||||
|
::Utility::String::split( splitString, description, "@@" );
|
||||||
|
for( vector<string>::size_type i = 0; i < splitString.size(); ++i )
|
||||||
|
{
|
||||||
|
if( i != 0 ) subStream << '\n';
|
||||||
|
subStream << ::Utility::String::trim( splitString[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
description = subStream.str();
|
||||||
|
|
||||||
|
subStream = stringstream();
|
||||||
|
}
|
||||||
|
|
||||||
|
while( !file.eof() )
|
||||||
|
{
|
||||||
|
::std::getline( file, str );
|
||||||
|
|
||||||
|
if( str.length() == 0 ) continue;
|
||||||
|
if( str[0] == '#' ) continue;
|
||||||
|
|
||||||
|
splitString = vector<string>();
|
||||||
|
::Utility::String::split( splitString, str, '#' );
|
||||||
|
|
||||||
|
if( splitString.size() == 0 ) continue;
|
||||||
|
if( splitString[0].length() == 0 ) continue;
|
||||||
|
|
||||||
|
subStream = stringstream( splitString[0] );
|
||||||
|
subStream >> str;
|
||||||
|
::Utility::String::toLowerCase( str );
|
||||||
|
|
||||||
|
if( str == "obj" )
|
||||||
|
{
|
||||||
|
vector<unsigned int> notUsed;
|
||||||
|
subStream >> str;
|
||||||
|
Object::importEntities( notUsed, workingDir + ::Utility::String::replaceCharacters(str, '/', '\\') + ".entity", transform );
|
||||||
|
}
|
||||||
|
else if( str == "o" )
|
||||||
|
{
|
||||||
|
subStream >> str;
|
||||||
|
string lowerCased = str;
|
||||||
|
::Utility::String::toLowerCase( lowerCased );
|
||||||
|
if( lowerCased == "spawnpoint" )
|
||||||
|
{
|
||||||
|
vector<Float4x4>::size_type i = spawnPoints.size();
|
||||||
|
spawnPoints.resize( i + 1 );
|
||||||
|
readOrientation( spawnPoints[i], subStream, transform );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Float4x4 orientation;
|
||||||
|
readOrientation( orientation, subStream, transform );
|
||||||
|
|
||||||
|
vector<Object>::size_type i = mapObjects.size();
|
||||||
|
mapObjects.resize( i + 1 );
|
||||||
|
|
||||||
|
mapObjects[i].setConfig( str );
|
||||||
|
if( mapObjects[i].getConfigID() == Object::invalidID )
|
||||||
|
{ // config handle not defined
|
||||||
|
mapObjects.resize( i );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Float3 scale = Float3( 1.0f );
|
||||||
|
::Utility::Stream::readFloats( scale, subStream, 3 );
|
||||||
|
|
||||||
|
mapObjects[i].setScaling( scale );
|
||||||
|
mapObjects[i].setOrientation( orientation );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
return Session::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Session::Failure;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Session::Session( )
|
||||||
|
: world(), effect(), objectIDLib(), state(MissingMap), player(), elapsedUpdatePeriod(0.0f),
|
||||||
|
spawnPoint(), staticObjects(), name(), description(), spawnPointOBJFile(), eventList(), nrPlayers(1), killsRequired(1) {}
|
||||||
|
|
||||||
|
Session::~Session( )
|
||||||
|
{
|
||||||
|
if ( this->effect.size() > 0 )
|
||||||
|
{
|
||||||
|
set<EffectCarrier*>::iterator i = this->effect.begin(),
|
||||||
|
end = this->effect.end();
|
||||||
|
for( ; i != end; ++i )
|
||||||
|
delete (*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Session::InitResult Session::load( const string &cMapFile )
|
||||||
|
{
|
||||||
|
this->state = Loading;
|
||||||
|
|
||||||
|
GameLUA::init();
|
||||||
|
|
||||||
|
this->effect = std::set<EffectCarrier*>();
|
||||||
|
this->objectIDLib = ::std::map<unsigned int, Object*>();
|
||||||
|
|
||||||
|
|
||||||
|
Float4x4 transform;
|
||||||
|
{
|
||||||
|
Float scale = 0.1f;
|
||||||
|
rotationMatrix_AxisY( transform, ::Utility::Value::radian(180.0f) );
|
||||||
|
transformMatrix( transform, scale * Float4x4::identity, transform );
|
||||||
|
transform.m44 = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
string mapFile(cMapFile);
|
||||||
|
::Utility::String::replaceCharacters( mapFile, '/', '\\' );
|
||||||
|
|
||||||
|
// importing world content
|
||||||
|
if( PrivateStatic::loadWorldFile( this->spawnPoint, this->staticObjects, this->name, this->description, mapFile, transform ) == Failure )
|
||||||
|
{
|
||||||
|
this->state = MissingMap;
|
||||||
|
return Failure;
|
||||||
|
}
|
||||||
|
this->spawnPointOBJFile = Object::getConfig( "spawnpoint" ).objFileName;
|
||||||
|
|
||||||
|
// importing player character content
|
||||||
|
vector<unsigned int> terrariConfigs, eldarishConfigs;
|
||||||
|
{
|
||||||
|
srand(time(0));
|
||||||
|
const char *terrariShipFiles[] = { "ship_TerrariCruiser.entity", "ship_TerrariInterceptor.entity", "ship_TerrariSniper.entity", "ship_TerrariSupport.entity" };
|
||||||
|
const char *eldarishShipFiles[] = { "ship_EldarishCruiser.entity", "ship_EldarishInterceptor.entity", "ship_EldarishSniper.entity", "ship_EldarishSupport.entity" };
|
||||||
|
|
||||||
|
string workingDir;
|
||||||
|
::Utility::String::extractDirPath( workingDir, mapFile, '\\' );
|
||||||
|
workingDir += "..\\entities\\";
|
||||||
|
|
||||||
|
vector<unsigned int> configIDOutput;
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < ::Utility::StaticArray::numElementsOf(terrariShipFiles); ++i )
|
||||||
|
{
|
||||||
|
if( Object::importEntities( configIDOutput, workingDir + terrariShipFiles[i], transform ) == Object::Failure )
|
||||||
|
return Failure;
|
||||||
|
PrivateStatic::append( terrariConfigs, configIDOutput );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < ::Utility::StaticArray::numElementsOf(eldarishShipFiles); ++i )
|
||||||
|
{
|
||||||
|
if( Object::importEntities( configIDOutput, workingDir + eldarishShipFiles[i], transform ) == Object::Failure )
|
||||||
|
return Failure;
|
||||||
|
PrivateStatic::append( eldarishConfigs, configIDOutput );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// resetting the physical world
|
||||||
|
this->world.emptyAndReInit( ::Utility::StaticArray::numElementsOf(this->player) + (unsigned int)this->staticObjects.size(), 2 );
|
||||||
|
|
||||||
|
// introduce players
|
||||||
|
for( unsigned char i = 0; i < ::Utility::StaticArray::numElementsOf(this->player); ++i )
|
||||||
|
{
|
||||||
|
this->player[i].session = this;
|
||||||
|
this->player[i].setPlayerID(i);
|
||||||
|
this->objectIDLib[this->player[i].getObjectID()] = &this->player[i];
|
||||||
|
|
||||||
|
if( i % 2 == 0 )
|
||||||
|
{ // lives and dies for the eldarish henceforth!
|
||||||
|
this->player[i].setConfig( eldarishConfigs[::std::rand() % eldarishConfigs.size()] );
|
||||||
|
this->player[i].setTeam( 0 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // lives and dies for the terrari henceforth!
|
||||||
|
this->player[i].setConfig( terrariConfigs[::std::rand() % terrariConfigs.size()] );
|
||||||
|
this->player[i].setTeam( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
this->player[i].setPhysicsID( this->world.addEntity( PrivateStatic::Player, &this->player[i], PrivateStatic::getBubbleOf(this->player[i]) ) );
|
||||||
|
this->player[i].moveToLimbo();
|
||||||
|
|
||||||
|
this->player[i].setPrimaryWeapon(Weapon::Test);
|
||||||
|
//this->player[i].setPrimaryWeapon(Weapon::Shotgun);
|
||||||
|
}
|
||||||
|
|
||||||
|
// introduce static objects
|
||||||
|
for( vector<Object>::size_type i = 0; i < this->staticObjects.size(); ++i )
|
||||||
|
{
|
||||||
|
this->objectIDLib[this->staticObjects[i].getObjectID()] = &this->staticObjects[i];
|
||||||
|
this->staticObjects[i].setPhysicsID( this->world.addEntity( PrivateStatic::Static, &this->staticObjects[i], PrivateStatic::getBubbleOf(this->staticObjects[i]) ) );
|
||||||
|
this->staticObjects[i].releaseFromLimbo();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->state = Running;
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char Session::getNumMaxPlayers( ) const
|
||||||
|
{ return ::Utility::StaticArray::numElementsOf(this->player); }
|
||||||
|
|
||||||
|
Player & Session::accessPlayer( unsigned int id )
|
||||||
|
{
|
||||||
|
return this->player[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::putInWorld( unsigned char playerID )
|
||||||
|
{ this->player[playerID].releaseFromLimbo(); }
|
||||||
|
|
||||||
|
void Session::putInLimbo( unsigned char playerID )
|
||||||
|
{ this->player[playerID].moveToLimbo(); }
|
||||||
|
|
||||||
|
void Session::addEffect( const EffectCarrier &effect )
|
||||||
|
{ this->effect.insert( effect.clone() ); }
|
||||||
|
|
||||||
|
const Session::State & Session::update( const Float &deltaTime )
|
||||||
|
{
|
||||||
|
float timeSlice = MoveAble::getDiscreteTimeSlice();
|
||||||
|
this->elapsedUpdatePeriod += deltaTime;
|
||||||
|
this->state = Idle;
|
||||||
|
|
||||||
|
// BENCHMARK BLOCK
|
||||||
|
//::Utility::WinTimer updateTimer;
|
||||||
|
// END BENCHMARK BLOCK
|
||||||
|
|
||||||
|
while( this->elapsedUpdatePeriod >= timeSlice )
|
||||||
|
{ // only perform update at a certain discrete updatePeriodicy. Several times if needing to catch up
|
||||||
|
this->elapsedUpdatePeriod -= timeSlice;
|
||||||
|
this->state = Updated;
|
||||||
|
|
||||||
|
// BENCHMARK BLOCK
|
||||||
|
//::Utility::WinTimer physicsTimer;
|
||||||
|
// END BENCHMARK BLOCK
|
||||||
|
|
||||||
|
{ // Update Effects
|
||||||
|
bool effectErased;
|
||||||
|
set<EffectCarrier*>::iterator i = this->effect.begin(),
|
||||||
|
end = this->effect.end();
|
||||||
|
while(i != end)
|
||||||
|
{
|
||||||
|
effectErased = false;
|
||||||
|
|
||||||
|
switch( (*i)->update( timeSlice ) )
|
||||||
|
{
|
||||||
|
case EffectCarrier::Dead:
|
||||||
|
delete (*i);
|
||||||
|
i = this->effect.erase( i );
|
||||||
|
effectErased = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case EffectCarrier::Armed:
|
||||||
|
{
|
||||||
|
switch( (*i)->getType() )
|
||||||
|
{
|
||||||
|
case EffectCarrier::Bullet:
|
||||||
|
{
|
||||||
|
Bullet::BulletCollector collector( (const Line*)(*i)->getVolumeOfEffect(), ::Utility::StaticArray::numElementsOf(this->player) );
|
||||||
|
unsigned int channel[] = { (unsigned int)Object::Player, (unsigned int)Object::Static };
|
||||||
|
|
||||||
|
this->world.visit( channel, ::Utility::StaticArray::numElementsOf(channel), (*i)->getVolumeOfEffect(), &collector );
|
||||||
|
if( collector.hitObjects.size() > 0 )
|
||||||
|
(*i)->onHit( collector.hitObjects, collector.hitPosW );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: case EffectCarrier::Undefined: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!effectErased)
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BENCHMARK BLOCK
|
||||||
|
//Benchmark::sampleTime( physicsTimer, 1 );
|
||||||
|
//physicsTimer.reset();
|
||||||
|
// END BENCHMARK BLOCK
|
||||||
|
|
||||||
|
{ // Update Players
|
||||||
|
// Iterating Player vs Object Collision physics
|
||||||
|
unsigned int channel[] = { (unsigned int)Object::Player, (unsigned int)Object::Static };
|
||||||
|
for( unsigned int i = 0; i < ::Utility::StaticArray::numElementsOf(this->player); ++i )
|
||||||
|
if( this->player[i].isActive() )
|
||||||
|
this->world.visit( channel, ::Utility::StaticArray::numElementsOf(channel), &this->player[i].body, &this->player[i], &Object::onCollisionAction );
|
||||||
|
|
||||||
|
// Apply accumulated physics and move players
|
||||||
|
for( unsigned int i = 0; i < ::Utility::StaticArray::numElementsOf(this->player); ++i )
|
||||||
|
{
|
||||||
|
if( this->player[i].isActive() )
|
||||||
|
this->player[i].update( timeSlice );
|
||||||
|
else if( i < nrPlayers )
|
||||||
|
this->player[i].spawn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BENCHMARK BLOCK
|
||||||
|
//Benchmark::sampleTime( physicsTimer, 2 );
|
||||||
|
// END BENCHMARK BLOCK
|
||||||
|
|
||||||
|
// TODO: recommended placement for powerUp manager update here
|
||||||
|
|
||||||
|
// move everything to their proper collision positions
|
||||||
|
this->world.update();
|
||||||
|
}
|
||||||
|
// How do we know when the game is over?
|
||||||
|
|
||||||
|
//This is how you end the game
|
||||||
|
/*
|
||||||
|
//GameEnded constructors takes the winning team ID as a variable
|
||||||
|
Event::GameEnded* test = new Event::GameEnded(0);
|
||||||
|
for (int i=0; i<PLAYERE_MAX_COUNT; i++)
|
||||||
|
{
|
||||||
|
//Get score from players
|
||||||
|
//test->setScore(i, player[i].getNumKills(), player[i].getNumDeaths(), player[i].getNumTeamKills());
|
||||||
|
test->setScore(i, rand()%15, rand()%10, rand()%5);
|
||||||
|
}
|
||||||
|
//Sort the score properly (should be done clientside instead really)
|
||||||
|
test->sortScore();
|
||||||
|
//Add it onto the event queue
|
||||||
|
eventList.push_back(test);
|
||||||
|
*/
|
||||||
|
|
||||||
|
//Client will now realize that the game is over once this packet is received
|
||||||
|
|
||||||
|
//printf("Exiting from update\n");
|
||||||
|
|
||||||
|
// BENCHMARK BLOCK
|
||||||
|
//Benchmark::sampleTime( updateTimer, 0 );
|
||||||
|
// END BENCHMARK BLOCK
|
||||||
|
|
||||||
|
// BENCHMARK BLOCK
|
||||||
|
//if( Benchmark::timerData[0].numSamples % 1000 == 0 )
|
||||||
|
// Benchmark::print();
|
||||||
|
// END BENCHMARK BLOCK
|
||||||
|
//Has a team won? Return -1 if not
|
||||||
|
int ct = CheckWinConditions();
|
||||||
|
if( -1 < ct )
|
||||||
|
{
|
||||||
|
Event::GameEvent *evt = new Event::GameEnded( ct );
|
||||||
|
addEvent( evt );
|
||||||
|
|
||||||
|
this->state = Over;
|
||||||
|
}
|
||||||
|
return this->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::writeToKeyFrame( KeyFrame &buffer )
|
||||||
|
{
|
||||||
|
// resetting buffer
|
||||||
|
buffer.numObjects = buffer.numParticles = 0;
|
||||||
|
|
||||||
|
// adding the Players
|
||||||
|
int numPlayers = ::Utility::Value::min( ::Utility::StaticArray::numElementsOf( this->player ),
|
||||||
|
::Utility::StaticArray::numElementsOf( buffer.Players ) );
|
||||||
|
for( int i = 0; i < numPlayers; ++i )
|
||||||
|
{
|
||||||
|
buffer.Players[i].Hp = this->player[i].hullPoints;
|
||||||
|
buffer.Players[i].Shield = this->player[i].shieldPoints;
|
||||||
|
buffer.Players[i].Special = this->player[i].specialID;
|
||||||
|
|
||||||
|
if( this->player[i].writeToKeyFrame( buffer ) == Object::Failure )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// adding the particles
|
||||||
|
set<EffectCarrier*>::const_iterator i = this->effect.begin(),
|
||||||
|
end = this->effect.end();
|
||||||
|
for( ; i != end; ++i )
|
||||||
|
if( (*i)->writeToKeyFrame( buffer ) == EffectCarrier::Failure )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::writeToRenderResourceData( ::Protocol::RenderData &data )
|
||||||
|
{
|
||||||
|
data.clear();
|
||||||
|
if( this->state == Session::Running )
|
||||||
|
{
|
||||||
|
for( vector<Object>::size_type i = 0; i < this->staticObjects.size(); ++i )
|
||||||
|
{ if( Object::getConfig( this->staticObjects[i].getConfigID() ).objFileName.length() > 0 )
|
||||||
|
data.mapData.add( this->staticObjects[i].getWorldPointMatrix(), Object::getConfig(this->staticObjects[i].getConfigID()).objFileName );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( this->spawnPointOBJFile.length() > 0 )
|
||||||
|
{ for( vector<Float4x4>::size_type i = 0; i < this->spawnPoint.size(); ++i )
|
||||||
|
data.mapData.add( this->spawnPoint[i], this->spawnPointOBJFile );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < ::Utility::StaticArray::numElementsOf(this->player); ++i )
|
||||||
|
data.playerData.addPlayer( Object::getConfig( this->player[i].getConfigID() ).objFileName );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::addEvent(Event::GameEvent *gameEvent)
|
||||||
|
{
|
||||||
|
eventList.push_back(gameEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::fetchEvents(std::vector<Event::GameEvent*> &list)
|
||||||
|
{
|
||||||
|
list=eventList;
|
||||||
|
eventList.resize(0);
|
||||||
|
}
|
||||||
|
void Session::fetchEffectData(std::vector<Network::EffectData> &effData)
|
||||||
|
{
|
||||||
|
// adding the effects
|
||||||
|
//int test= effect.size();
|
||||||
|
//effData.resize(effect.size());
|
||||||
|
//effData.
|
||||||
|
//int count=0;
|
||||||
|
effData.resize(0);
|
||||||
|
Network::EffectData tmp;
|
||||||
|
set<EffectCarrier*>::const_iterator i = this->effect.begin(),
|
||||||
|
end = this->effect.end();
|
||||||
|
for( ; i != end; ++i )
|
||||||
|
{
|
||||||
|
if( (*i)->writeToNetEffect( tmp ) != EffectCarrier::Failure )
|
||||||
|
{
|
||||||
|
//effData[count]=tmp;
|
||||||
|
effData.push_back(tmp);
|
||||||
|
//count++;
|
||||||
|
//break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int Session::CheckWinConditions()
|
||||||
|
{
|
||||||
|
int count=0;
|
||||||
|
for (int i=0; i<nrPlayers; i+=2)
|
||||||
|
{
|
||||||
|
count+=player[i].killCount;
|
||||||
|
}
|
||||||
|
if (count>=killsRequired)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
count=0;
|
||||||
|
for (int i=1; i<nrPlayers; i+=2)
|
||||||
|
{
|
||||||
|
count+=player[i].killCount;
|
||||||
|
}
|
||||||
|
if (count>=killsRequired)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef GAME_SESSION_H
|
||||||
|
#define GAME_SESSION_H
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
#include "OysterGame.h"
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "Object.h"
|
||||||
|
#include "EffectCarrier.h"
|
||||||
|
#include "Player.h"
|
||||||
|
#include "Network.h"
|
||||||
|
|
||||||
|
namespace GameLogic
|
||||||
|
{
|
||||||
|
class Session
|
||||||
|
{
|
||||||
|
friend class Player;
|
||||||
|
public:
|
||||||
|
enum InitResult { Success, Failure };
|
||||||
|
enum State { MissingMap, Loading, Running, Updated, Idle, Over };
|
||||||
|
|
||||||
|
Session( );
|
||||||
|
~Session( );
|
||||||
|
|
||||||
|
InitResult load( const ::std::string &mapFile );
|
||||||
|
|
||||||
|
unsigned char getNumMaxPlayers( ) const;
|
||||||
|
Player & accessPlayer( unsigned int id );
|
||||||
|
void putInWorld( unsigned char playerID );
|
||||||
|
void putInLimbo( unsigned char playerID );
|
||||||
|
|
||||||
|
void addEffect( const EffectCarrier &effect );
|
||||||
|
|
||||||
|
void writeToKeyFrame( KeyFrame &buffer );
|
||||||
|
void writeToRenderResourceData( ::Protocol::RenderData &data );
|
||||||
|
|
||||||
|
const State & update( const ::Oyster::Math::Float &deltaTime );
|
||||||
|
|
||||||
|
void addEvent(Event::GameEvent *gameEvent);
|
||||||
|
void fetchEvents(std::vector<Event::GameEvent*> &list);
|
||||||
|
void fetchEffectData(std::vector<Network::EffectData> &effData);
|
||||||
|
|
||||||
|
//No need for mutex etc, this should only be called before start
|
||||||
|
void setNrPlayers(int pc){nrPlayers=pc;}
|
||||||
|
void setKillsRequired(int kr){killsRequired=kr;}
|
||||||
|
|
||||||
|
int CheckWinConditions();
|
||||||
|
private:
|
||||||
|
//Different from max nr, it's the actual count
|
||||||
|
int nrPlayers;
|
||||||
|
int killsRequired;
|
||||||
|
::Oyster::Game::CollisionHandler<Object> world;
|
||||||
|
::std::set<EffectCarrier*> effect;
|
||||||
|
::std::map<unsigned int, Object*> objectIDLib;
|
||||||
|
State state;
|
||||||
|
Player player[8];
|
||||||
|
::Oyster::Math::Float elapsedUpdatePeriod;
|
||||||
|
|
||||||
|
::std::vector<::Oyster::Math::Float4x4> spawnPoint;
|
||||||
|
::std::vector<Object> staticObjects;
|
||||||
|
::std::string name, description, spawnPointOBJFile;
|
||||||
|
|
||||||
|
std::vector<Event::GameEvent*> eventList;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,66 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "Ship.h"
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "SoundEngine.h"
|
||||||
|
|
||||||
|
using namespace ::Game;
|
||||||
|
using namespace ::GameLogic;
|
||||||
|
using namespace ::Oyster;
|
||||||
|
using namespace ::Oyster::Math;
|
||||||
|
|
||||||
|
Ship::Ship( const Float4x4 &orientation, const Float3 ¢erOfMass ) :
|
||||||
|
Object(orientation, centerOfMass), transform(Math::Float4x4::identity), worldOutOfDate(true), updatePeriod(0.0f)
|
||||||
|
{
|
||||||
|
this->engineSound = SoundEngine::CreateSoundSource();
|
||||||
|
this->engineSound->SetResource("..\\Content\\Sounds\\engine.wav");
|
||||||
|
this->engineSound->SetLooping(true);
|
||||||
|
this->engineSound->SetVolume(1.0f);
|
||||||
|
//this->engineSound->Play();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ship::~Ship( )
|
||||||
|
{
|
||||||
|
SoundEngine::DestroySoundSource(this->engineSound);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ship::update( const ::Oyster::Math::Float &deltaTime )
|
||||||
|
{
|
||||||
|
this->updatePeriod += deltaTime;
|
||||||
|
if( this->updatePeriod >= MoveAble::getDiscreteTimeSlice() )
|
||||||
|
{
|
||||||
|
this->updatePeriod -= MoveAble::getDiscreteTimeSlice();
|
||||||
|
Object::update( );
|
||||||
|
}
|
||||||
|
|
||||||
|
Math::transformMatrix( this->world, this->transform, this->body.orientation );
|
||||||
|
this->worldOutOfDate = false;
|
||||||
|
|
||||||
|
this->engineSound->SetPosition( this->body.orientation.v[3] );
|
||||||
|
}
|
||||||
|
|
||||||
|
const Math::Float4x4 & Ship::getWorldMatrix( ) const
|
||||||
|
{
|
||||||
|
if( this->worldOutOfDate )
|
||||||
|
{
|
||||||
|
Math::transformMatrix( this->world, this->transform, this->body.orientation );
|
||||||
|
this->worldOutOfDate = false;
|
||||||
|
}
|
||||||
|
return this->world;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ship::setMutation( const Math::Float4x4 &matrix )
|
||||||
|
{
|
||||||
|
this->transform = matrix;
|
||||||
|
this->worldOutOfDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ship::applyDamage( unsigned int magnitude, const Object &attacker )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ship::applyHeal( unsigned int magnitude )
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by Dan Andersson 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef GAME_SHIP_H
|
||||||
|
#define GAME_SHIP_H
|
||||||
|
|
||||||
|
#include "Object.h"
|
||||||
|
#include "SoundSource.h"
|
||||||
|
|
||||||
|
namespace Game
|
||||||
|
{
|
||||||
|
class Ship : public ::GameLogic::Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Ship( const ::Oyster::Math::Float4x4 &orientation = ::Oyster::Math::Float4x4::identity, const ::Oyster::Math::Float3 ¢erOfMass = ::Oyster::Math::Float3::null );
|
||||||
|
virtual ~Ship( );
|
||||||
|
|
||||||
|
virtual void update( const ::Oyster::Math::Float &deltaTime );
|
||||||
|
const ::Oyster::Math::Float4x4 & getWorldMatrix( ) const;
|
||||||
|
void setMutation( const ::Oyster::Math::Float4x4 &matrix );
|
||||||
|
|
||||||
|
virtual void applyDamage( unsigned int magnitude, const Object &attacker );
|
||||||
|
virtual void applyHeal( unsigned int magnitude );
|
||||||
|
|
||||||
|
private:
|
||||||
|
::Oyster::Math::Float4x4 transform;
|
||||||
|
mutable ::Oyster::Math::Float4x4 world;
|
||||||
|
mutable bool worldOutOfDate;
|
||||||
|
::Oyster::Math::Float updatePeriod;
|
||||||
|
|
||||||
|
SoundSource *engineSound;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "Weapon.h"
|
||||||
|
|
||||||
|
using namespace GameLogic;
|
||||||
|
|
||||||
|
const Weapon Weapon::weapons[Weapon::Count] =
|
||||||
|
{
|
||||||
|
{"../Content/Scripts/weapon_test.lua", "test_OnFire", "test_OnUpdate", "test_OnHit"}, // WeaponType::Test
|
||||||
|
{"../Content/Scripts/weapon_shotgun.lua", "shotgun_OnFire", "shotgun_OnUpdate", "shotgun_OnHit"}, // WeaponType::Shotgun
|
||||||
|
{"../Content/Scripts/PowerUpManager.lua", "PowerUp_OnFire", "PowerUp_OnUpdate", "PowerUp_OnHit"} // WeaponType::PowerUpManager
|
||||||
|
};
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef WEAPON_H
|
||||||
|
#define WEAPON_H
|
||||||
|
|
||||||
|
namespace GameLogic
|
||||||
|
{
|
||||||
|
class Weapon
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
Test = 0,
|
||||||
|
Shotgun,
|
||||||
|
Powerup,
|
||||||
|
Count,
|
||||||
|
Undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *scriptFile;
|
||||||
|
const char *onFireFunction;
|
||||||
|
const char *onUpdateFunction;
|
||||||
|
const char *onHitFunction;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const Weapon weapons[Weapon::Count];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,114 @@
|
||||||
|
#include "GameEndedMenu.h"
|
||||||
|
#include "RenderEngine.h"
|
||||||
|
#include "Input\InputController.h"
|
||||||
|
#include "Window\Window.h"
|
||||||
|
#include "Lobby.h"
|
||||||
|
|
||||||
|
Oyster::Math::Float3 MainMenuPos, WinnerPos;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GameEndedMenu::GameEndedMenu(Player *players[], Score* scores, int winningTeam)
|
||||||
|
{
|
||||||
|
m_stateStack = NULL;
|
||||||
|
winner=winningTeam;
|
||||||
|
for (int i=0; i< PLAYER_MAX_COUNT; i++)
|
||||||
|
{
|
||||||
|
this->scoreboard[i]=scores[i];
|
||||||
|
playerList[i]=players[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GameEndedMenu::~GameEndedMenu()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameEndedMenu::Enter(GameStateStack *stateStack)
|
||||||
|
{
|
||||||
|
|
||||||
|
Oyster::Input::Controller::OrigoTopLeft();
|
||||||
|
Oyster::Input::Controller::RestrictMouse(false);
|
||||||
|
|
||||||
|
m_stateStack = stateStack;
|
||||||
|
|
||||||
|
Oyster::Math::Float2 windowSize;
|
||||||
|
windowSize.x = (float)Oyster::Window::Size.right;
|
||||||
|
windowSize.y = (float)Oyster::Window::Size.top;
|
||||||
|
|
||||||
|
D3DX11CreateShaderResourceViewFromFile(Oyster::Core::Device, "..\\Content\\GUI\\button_darkblue_250x64.png", NULL, NULL, &m_quitTextures[0], NULL);
|
||||||
|
D3DX11CreateShaderResourceViewFromFile(Oyster::Core::Device, "..\\Content\\GUI\\button_250x64.png", NULL, NULL, &m_quitTextures[1], NULL);
|
||||||
|
D3DX11CreateShaderResourceViewFromFile(Oyster::Core::Device, "..\\Content\\GUI\\lobby_bg_screen.png", NULL, NULL, &m_backgroundOverlay.texture, NULL);
|
||||||
|
|
||||||
|
m_backgroundOverlay.size = windowSize;
|
||||||
|
m_backgroundOverlay.position.x = 0.0f;
|
||||||
|
m_backgroundOverlay.position.y = 0.0f;
|
||||||
|
m_backgroundOverlay.position.z = 0.5f;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
m_quitOverlay.texture = m_quitTextures[0];
|
||||||
|
m_quitOverlay.size = Oyster::Math::Float2(132.0f, 83.0f);
|
||||||
|
m_quitOverlay.position.x = windowSize.x / 2.0f - m_quitOverlay.size.x / 2.0f;
|
||||||
|
m_quitOverlay.position.y = windowSize.y - m_quitOverlay.size.y - 20.0f;
|
||||||
|
m_quitOverlay.position.z = 0.0f;
|
||||||
|
|
||||||
|
MainMenuPos = m_quitOverlay.position;
|
||||||
|
MainMenuPos.x+=10;
|
||||||
|
MainMenuPos.y+=5;
|
||||||
|
|
||||||
|
WinnerPos.x = 120.0f;
|
||||||
|
WinnerPos.y = 10.0f;
|
||||||
|
WinnerPos.z = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameEndedMenu::Exit()
|
||||||
|
{
|
||||||
|
m_stateStack = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameEndedMenu::Suspend()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameEndedMenu::Resume()
|
||||||
|
{
|
||||||
|
Oyster::Input::Controller::OrigoTopLeft();
|
||||||
|
Oyster::Input::Controller::RestrictMouse(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameEndedMenu::Update(float timeDelta)
|
||||||
|
{
|
||||||
|
|
||||||
|
Oyster::Math::Float2 cursorPosition = Oyster::Math::Float2((float)Oyster::Input::Controller::GetX(), (float)Oyster::Input::Controller::GetY());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (IntersectsOverlay(m_quitOverlay, cursorPosition))
|
||||||
|
m_quitOverlay.texture = m_quitTextures[1];
|
||||||
|
else
|
||||||
|
m_quitOverlay.texture = m_quitTextures[0];
|
||||||
|
|
||||||
|
if (Oyster::Input::Controller::isMouseBtnPressed(MK_LBUTTON))
|
||||||
|
{
|
||||||
|
if (IntersectsOverlay(m_quitOverlay, cursorPosition))
|
||||||
|
{
|
||||||
|
m_stateStack->SetState(new MainMenu());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameEndedMenu::Render() const
|
||||||
|
{
|
||||||
|
RenderEngine::RenderScoreboard(this->scoreboard, PLAYER_MAX_COUNT, playerList);
|
||||||
|
Oyster::Engine::PrepareForRendering::Begin2DTextRender();
|
||||||
|
//Oyster::Engine::Render::Text("Into The Void!",Oyster::Math::Float2(20,50), TitlePos);
|
||||||
|
Oyster::Engine::Render::Text(SSTR("Team "<<winner+1<<" won the game."),Oyster::Math::Float2(15,50), WinnerPos);
|
||||||
|
Oyster::Engine::Render::Text("Quit",Oyster::Math::Float2(15,40),MainMenuPos);
|
||||||
|
|
||||||
|
Oyster::Engine::PrepareForRendering::Begin2DRender();
|
||||||
|
|
||||||
|
Oyster::Engine::Render::Sprite(m_backgroundOverlay.texture, m_backgroundOverlay.size, m_backgroundOverlay.position);
|
||||||
|
Oyster::Engine::Render::Sprite(m_quitOverlay.texture, m_quitOverlay.size, m_quitOverlay.position);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "GameState.h"
|
||||||
|
#include "OysterMath.h"
|
||||||
|
#include "RenderEngine.h"
|
||||||
|
#include "NetworkConstants.h"
|
||||||
|
#include "NetworkMiscFunctions.h"
|
||||||
|
#include "MainMenu.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class GameEndedMenu : public GameState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GameEndedMenu(Player *players[], Score* scores, int winningTeam);
|
||||||
|
virtual ~GameEndedMenu();
|
||||||
|
|
||||||
|
void Enter(GameStateStack *stateStack);
|
||||||
|
void Exit();
|
||||||
|
|
||||||
|
void Suspend();
|
||||||
|
void Resume();
|
||||||
|
|
||||||
|
void Update(float timeDelta);
|
||||||
|
void Render() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int winner;
|
||||||
|
Score scoreboard[PLAYER_MAX_COUNT];
|
||||||
|
Player *playerList[PLAYER_MAX_COUNT];
|
||||||
|
GameStateStack *m_stateStack;
|
||||||
|
|
||||||
|
ID3D11ShaderResourceView *m_quitTextures[2];
|
||||||
|
|
||||||
|
Overlay m_backgroundOverlay;
|
||||||
|
Overlay m_quitOverlay;
|
||||||
|
};
|
|
@ -0,0 +1,33 @@
|
||||||
|
#pragma once
|
||||||
|
#ifndef GAMESTATE_H
|
||||||
|
#define GAMESTATE_H
|
||||||
|
|
||||||
|
#include "GameStateStack.h"
|
||||||
|
|
||||||
|
class GameState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~GameState() {}
|
||||||
|
|
||||||
|
virtual void Enter(GameStateStack *stateStack) = 0;
|
||||||
|
virtual void Exit() = 0;
|
||||||
|
|
||||||
|
virtual void Suspend() = 0;
|
||||||
|
virtual void Resume() = 0;
|
||||||
|
|
||||||
|
virtual void Update(float timeDelta) = 0;
|
||||||
|
virtual void Render() const = 0;
|
||||||
|
|
||||||
|
// If this function returns true, the GameState will recieve updates even while it's suspended.
|
||||||
|
virtual bool WantsBackgroundUpdates() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool IsTransparent() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,114 @@
|
||||||
|
#include <cassert>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "GameStateStack.h"
|
||||||
|
#include "GameState.h"
|
||||||
|
|
||||||
|
GameStateStack::GameStateStack(GameState *initialState)
|
||||||
|
{
|
||||||
|
PushState(initialState);
|
||||||
|
}
|
||||||
|
|
||||||
|
GameStateStack::~GameStateStack()
|
||||||
|
{
|
||||||
|
GameState *state;
|
||||||
|
|
||||||
|
while(!m_stack.empty())
|
||||||
|
{
|
||||||
|
state = m_stack.back();
|
||||||
|
m_stack.pop_back();
|
||||||
|
|
||||||
|
state->Exit();
|
||||||
|
delete state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameStateStack::Update(float timeDelta)
|
||||||
|
{
|
||||||
|
if (m_stack.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_stack.back()->Update(timeDelta);
|
||||||
|
|
||||||
|
for(int i = 0; i < std::max((int)m_stack.size() - 1, 0); i++)
|
||||||
|
{
|
||||||
|
if (m_stack[i]->WantsBackgroundUpdates())
|
||||||
|
m_stack[i]->Update(timeDelta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameStateStack::Render()
|
||||||
|
{
|
||||||
|
if (m_stack.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
size_t lastOpaque = m_stack.size() - 1;
|
||||||
|
|
||||||
|
while(lastOpaque > 0 && m_stack[lastOpaque]->IsTransparent())
|
||||||
|
{
|
||||||
|
lastOpaque--;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = lastOpaque; i < m_stack.size(); i++)
|
||||||
|
{
|
||||||
|
m_stack[i]->Render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GameState *GameStateStack::CurrentState()
|
||||||
|
{
|
||||||
|
return m_stack.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GameStateStack::GetStackSize()
|
||||||
|
{
|
||||||
|
return m_stack.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameStateStack::isEmpty()
|
||||||
|
{
|
||||||
|
return m_stack.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameStateStack::SetState(GameState *state)
|
||||||
|
{
|
||||||
|
GameState *oldState;
|
||||||
|
|
||||||
|
while(!m_stack.empty())
|
||||||
|
{
|
||||||
|
oldState = m_stack.back();
|
||||||
|
m_stack.pop_back();
|
||||||
|
|
||||||
|
oldState->Exit();
|
||||||
|
delete oldState;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state)
|
||||||
|
{
|
||||||
|
m_stack.push_back(state);
|
||||||
|
state->Enter(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameStateStack::PushState(GameState *state)
|
||||||
|
{
|
||||||
|
if (!m_stack.empty())
|
||||||
|
m_stack.back()->Suspend();
|
||||||
|
|
||||||
|
m_stack.push_back(state);
|
||||||
|
state->Enter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameStateStack::PopState()
|
||||||
|
{
|
||||||
|
assert(!m_stack.empty());
|
||||||
|
|
||||||
|
GameState *state = m_stack.back();
|
||||||
|
m_stack.pop_back();
|
||||||
|
|
||||||
|
state->Exit();
|
||||||
|
delete state;
|
||||||
|
|
||||||
|
if (!m_stack.empty())
|
||||||
|
m_stack.back()->Resume();
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
#pragma once
|
||||||
|
#ifndef GAMESTATESTACK_H
|
||||||
|
#define GAMESTATESTACK_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class GameState;
|
||||||
|
|
||||||
|
class GameStateStack
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GameStateStack(GameState *initialState);
|
||||||
|
virtual ~GameStateStack();
|
||||||
|
|
||||||
|
void Update(float timeDelta);
|
||||||
|
void Render();
|
||||||
|
|
||||||
|
GameState *CurrentState();
|
||||||
|
size_t GetStackSize();
|
||||||
|
|
||||||
|
bool isEmpty();
|
||||||
|
|
||||||
|
// The GameStateStack takes ownership of the state when it's pushed on the stack, and will delete it when it's popped.
|
||||||
|
|
||||||
|
// SetState pops all gamestates currently on the stack and then pushes the new state on the stack.
|
||||||
|
void SetState(GameState *state);
|
||||||
|
void PushState(GameState *state);
|
||||||
|
void PopState();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<GameState *> m_stack;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
#ifndef GRAHIC_STRUCTS_H
|
||||||
|
#define GRAHIC_STRUCTS_H
|
||||||
|
|
||||||
|
#include "OysterCollision.h"
|
||||||
|
|
||||||
|
namespace GraphicStruct
|
||||||
|
{
|
||||||
|
|
||||||
|
struct PointLight
|
||||||
|
{
|
||||||
|
struct{ ::Oyster::Math::Float3 center; ::Oyster::Math::Float radius; } pos;
|
||||||
|
::Oyster::Math::Float3 color;
|
||||||
|
::Oyster::Math::Float intensty;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LightData
|
||||||
|
{
|
||||||
|
::Oyster::Math::Float4x4 viewMatrix, projectionMatrix;
|
||||||
|
::LinearAlgebra::Vector3<unsigned int> numDispatches;
|
||||||
|
unsigned int reservedPadding;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue