First commit

This commit is contained in:
CarlDenisAndersen 2013-10-23 00:09:17 +02:00
parent 2885926e15
commit c398fa4da4
174 changed files with 19902 additions and 0 deletions

65
Engine/Collision/Box.cpp Normal file
View File

@ -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

44
Engine/Collision/Box.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 &centerDistance, 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 &centerDistance, 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;
}
} } }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

40
Engine/Collision/Line.cpp Normal file
View File

@ -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

39
Engine/Collision/Line.h Normal file
View File

@ -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

View File

@ -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"

View File

@ -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

38
Engine/Collision/Plane.h Normal file
View File

@ -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

View File

@ -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

37
Engine/Collision/Point.h Normal file
View File

@ -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

54
Engine/Collision/Ray.cpp Normal file
View File

@ -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

42
Engine/Collision/Ray.h Normal file
View File

@ -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

View File

@ -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

37
Engine/Collision/Sphere.h Normal file
View File

@ -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

202
Engine/Core/Buffer.cpp Normal file
View File

@ -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;
}

76
Engine/Core/Buffer.h Normal file
View File

@ -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

164
Engine/Core/Core.cpp Normal file
View File

@ -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;
}

30
Engine/Core/Core.h Normal file
View File

@ -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

View File

@ -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

539
Engine/Engine.cpp Normal file
View File

@ -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;
}

177
Engine/Engine.h Normal file
View File

@ -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

38
Engine/EngineIncludes.h Normal file
View File

@ -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"

View File

@ -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;
}

View File

@ -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);
};
}
}

View File

@ -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

View File

@ -0,0 +1 @@
#include "GameObject.h"

22
Engine/Game/GameObject.h Normal file
View File

@ -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

119
Engine/Game/MoveAble.cpp Normal file
View File

@ -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 );
}

57
Engine/Game/MoveAble.h Normal file
View File

@ -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

3
Engine/Game/OysterGame.h Normal file
View File

@ -0,0 +1,3 @@
#include "MoveAble.h"
#include "CollisionHandler.h"
#include "SateliteCamera.h"

View File

@ -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;
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

268
Engine/Math/LinearMath.h Normal file
View File

@ -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> &centerOfMass = 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

761
Engine/Math/Matrix.h Normal file
View File

@ -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

View File

@ -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;
}
} }

220
Engine/Math/OysterMath.h Normal file
View File

@ -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 &centerOfMass = 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

183
Engine/Math/Quaternion.h Normal file
View File

@ -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

659
Engine/Math/Vector.h Normal file
View File

@ -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

216
Engine/Misc/Utilities.cpp Normal file
View File

@ -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;
}
}
}

80
Engine/Misc/Utilities.h Normal file
View File

@ -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 &degree )
{ return degree * (3.1415926535897932384626433832795f / 180.0f); }
template<typename ValueType>
inline ValueType degree( const ValueType &radian )
{ return radian * (180.0f / 3.1415926535897932384626433832795f); }
}
}
#endif

75
Engine/Misc/WinTimer.cpp Normal file
View File

@ -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( &currentTick );
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( &currentTick );
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( &currentTick );
return currentTick;
}

32
Engine/Misc/WinTimer.h Normal file
View File

@ -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

157
Engine/Render/Camera.cpp Normal file
View File

@ -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;
}

61
Engine/Render/Camera.h Normal file
View File

@ -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;
};
}
}

8
Engine/Render/Lights.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include "Engine\Math\OysterMath.h"
struct DirectionalLight
{
Oyster::Math::Float4 Irradiance;
Oyster::Math::Float4 Direction;
};

0
Engine/Render/Model.cpp Normal file
View File

32
Engine/Render/Model.h Normal file
View File

@ -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

29
Engine/Render/ModelInfo.h Normal file
View File

@ -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

165
Engine/Render/TextBox.cpp Normal file
View File

@ -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
//}
}

67
Engine/Render/TextBox.h Normal file
View File

@ -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);
};
}
}

View File

@ -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);
}
}
}

View File

@ -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();
};
}
}

View File

@ -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;
};
};
}
}

View File

@ -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;
}

View File

@ -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;
};
}
}

View File

@ -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();
}

View File

@ -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

View File

@ -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},
};
}
}

View File

@ -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];
};
}
}

253
Engine/Shader/Shader.cpp Normal file
View File

@ -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);
}
}

78
Engine/Shader/Shader.h Normal file
View File

@ -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();
};
}

164
Engine/Window/Window.cpp Normal file
View File

@ -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;
}

46
Engine/Window/Window.h Normal file
View File

@ -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);
};
}

154
GameLogic/Bullet.cpp Normal file
View File

@ -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 );
}

58
GameLogic/Bullet.h Normal file
View File

@ -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

View File

@ -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;
}

77
GameLogic/EffectCarrier.h Normal file
View File

@ -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

297
GameLogic/GameLUA.cpp Normal file
View File

@ -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);
}
}

32
GameLogic/GameLUA.h Normal file
View File

@ -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

12
GameLogic/GameLogic.cpp Normal file
View File

@ -0,0 +1,12 @@
#include "GameLogic.h"
using ::std::string;
namespace GameLogic
{
Result init( const string &iniFile )
{
// TODO
return Success;
}
}

14
GameLogic/GameLogic.h Normal file
View File

@ -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

View File

@ -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 );
}

View File

@ -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

46
GameLogic/MoveAble.h Normal file
View File

@ -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 &centerOfMass = 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

485
GameLogic/Object.cpp Normal file
View File

@ -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 &centerOfMass )
: 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 &centerOfMass )
: 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() ); }
} }

147
GameLogic/Object.h Normal file
View File

@ -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 &centerOfMass = ::Oyster::Math::Float3::null );
Object( const ::Oyster::Collision::Box &body, const ::Oyster::Math::Float3 &centerOfMass = ::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

241
GameLogic/Player.cpp Normal file
View File

@ -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 &centerOfMass ) : 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 &centerOfMass ) : 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;
}

83
GameLogic/Player.h Normal file
View File

@ -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 &centerOfMass = ::Oyster::Math::Float3::null );
Player( const ::Oyster::Collision::Box &body, const ::Oyster::Math::Float3 &centerOfMass = ::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

320
GameLogic/Protocoll.cpp Normal file
View File

@ -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 );
}
}

161
GameLogic/Protocoll.h Normal file
View File

@ -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 );
};
}

576
GameLogic/Session.cpp Normal file
View File

@ -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;
}

72
GameLogic/Session.h Normal file
View File

@ -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

66
GameLogic/Ship.cpp Normal file
View File

@ -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 &centerOfMass ) :
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 )
{
}

37
GameLogic/Ship.h Normal file
View File

@ -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 &centerOfMass = ::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

12
GameLogic/Weapon.cpp Normal file
View File

@ -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
};

28
GameLogic/Weapon.h Normal file
View File

@ -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

View File

@ -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);
}

View File

@ -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;
};

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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