1 #include <glPortal/Editor.hpp>
namespace glPortal {
5 Editor::Editor( Window &win, World &w )
: window( win ), world( w ) {
}
9 void Editor::render( ) {
}
1 #include <glPortal/Game.hpp>
#include <glPortal/GameState.hpp>
#include <iostream>
#include <radix/component/Trigger.hpp>
#include <radix/component/Player.hpp>
using namespace radix;
namespace glPortal {
12 Game::Game( ) {
windowTitle = "GlPortal";
defaultMap = "/maps/n1.xml";
}
17 void Game::initHook( ) {
initFunctionStack( );
gameController = std::make_unique<GameController>( this );
initRenderers( );
addRenderers( );
}
24 void Game::initFunctionStack( ) {
world.stateFunctionStack.push( &GameState::handleRunning );
world.stateFunctionStack.push( &GameState::handleSplash );
}
29 void Game::processInput( ) {
gameController->processInput( );
}
33 void Game::update( ) {
BaseGame::update( );
dtime = ( currentTime-lastRender )/1000.;
}
38 void Game::initRenderers( ) {
World& worldReference = static_cast<glPortal::World&>( world );
radix::Renderer& rendererReference = *renderer.get( );
gameRenderer =
std::make_unique<GameRenderer>( worldReference, rendererReference, camera.get( ), &dtime );
uiRenderer =
std::make_unique<UiRenderer>( worldReference, rendererReference );
}
48 void Game::addRenderers( ) {
renderer->addRenderer( *gameRenderer );
renderer->addRenderer( *uiRenderer );
}
} /* namespace glPortal */
1 #include <glPortal/GameController.hpp>
#include <glPortal/Game.hpp>
#include <radix/env/Environment.hpp>
#include <radix/component/Player.hpp>
#include <glPortal/GameState.hpp>
namespace glPortal {
10 GameController::GameController( Game *game ) {
this->game = game;
this->world = static_cast<World*>( game->getWorld( ) );
this->gameState = std::make_unique<radix::GameState>( );
GameState::init( *game );
initObservers( );
}
18 void GameController::initObservers( ) {
this->closeWindowHolder = game->getWorld( )->event.addObserver(
radix::InputSource::WindowCloseEvent::Type, [this]( const radix::Event& event ) {
this->game->close( );
} );
}
25 void GameController::processInput( ) {
game->getWindow( ).processEvents( );
if ( game->getWindow( ).isKeyDown( SDL_SCANCODE_Q ) ) {
game->close( );
}
gameState->handleInput( *game );
}
} /* namespace glPortal */
1 #include <glPortal/GameState.hpp>
#include <glPortal/Game.hpp>
#include <radix/data/screen/XmlScreenLoader.hpp>
#include <radix/env/Environment.hpp>
#include <radix/component/Player.hpp>
namespace glPortal {
radix::EventDispatcher::CallbackHolder GameState::splashCallbackHolder;
radix::EventDispatcher::CallbackHolder GameState::winCallbackHolder;
13 void GameState::init( radix::BaseGame &game ) {
winCallbackHolder = game.getWorld( )->event.addObserver
(
radix::GameState::WinEvent::Type, [&game]( const radix::Event &event ) {
game.getWorld( )->stateFunctionStack.push( &GameState::handleGameOverScreen );
}
);
winCallbackHolder.setStatic( );
}
24 void GameState::handleRunning( radix::BaseGame &game ) {
radix::Player &player = game.getWorld( )->getPlayer( ).getComponent<radix::Player>( );
player.frozen = false;
game.getWorld( )->event.removeObserver( splashCallbackHolder );
splashCallbackHolder = game.getWorld( )->event.addObserver
(
radix::InputSource::KeyReleasedEvent::Type, [&player, &game]( const radix::Event& event ) {
const int key = ( ( radix::InputSource::KeyReleasedEvent & ) event ).key;
if ( key == SDL_SCANCODE_ESCAPE ) {
player.frozen = true;
game.getWorld( )->stateFunctionStack.push( &GameState::handlePaused );
}
} );
if ( !splashCallbackHolder.getStatic( ) ) {
splashCallbackHolder.setStatic( );
}
}
45 void GameState::handlePaused( radix::BaseGame &game ) {
radix::Screen &screen = radix::XmlScreenLoader::getScreen( radix::Environment::getDataDir( )
+ "/screens/title.xml" );
game.getGameWorld( )->addScreen( screen );
radix::Player &player = game.getWorld( )->getPlayer( ).getComponent<radix::Player>( );
game.getWorld( )->event.removeObserver( splashCallbackHolder );
splashCallbackHolder = game.getWorld( )->event.addObserver
(
radix::InputSource::KeyReleasedEvent::Type, [&player, &game] ( const radix::Event& event ) {
const int key = ( ( radix::InputSource::KeyReleasedEvent & ) event ).key;
if ( key == SDL_SCANCODE_ESCAPE ) {
player.frozen = false;
game.getWorld( )->stateFunctionStack.pop( );
}
} );
}
64 void GameState::handleSplash( radix::BaseGame &game ) {
radix::Player &player = game.getWorld( )->getPlayer( ).getComponent<radix::Player>( );
player.frozen = true;
radix::Screen &screen =
radix::XmlScreenLoader::getScreen( radix::Environment::getDataDir( ) + "/screens/test.xml" );
game.getGameWorld( )->addScreen( screen );
if ( game.getWindow( ).isKeyDown( SDL_SCANCODE_RETURN ) ) {
game.getWorld( )->stateFunctionStack.pop( );
}
}
75 void GameState::handleMenu( radix::BaseGame &game ) { }
77 void GameState::handleGameOverScreen( radix::BaseGame &game ) {
radix::Player &player = game.getWorld( )->getPlayer( ).getComponent<radix::Player>( );
player.frozen = true;
radix::Screen &screen =
radix::XmlScreenLoader::getScreen( radix::Environment::getDataDir( ) + "/screens/end.xml" );
game.getGameWorld( )->addScreen( screen );
}
85 void GameState::handleWinScreen( radix::BaseGame &game ) { }
} /* namespace glPortal */
1 #include <glPortal/Game.hpp>
#include <radix/env/Environment.hpp>
#include <radix/env/ArgumentsParser.hpp>
#include <radix/core/diag/Throwables.hpp>
using namespace glPortal;
9 int main( const int argc, char *argv[] ) {
radix::Util::Init( );
radix::ArgumentsParser::setEnvironmentFromArgs( argc, argv );
try {
Game game;
game.setup( );
while ( game.isRunning( ) ) {
game.processInput( );
game.update( );
game.render( );
}
game.cleanUp( );
} catch ( radix::Exception::Error &err ) {
radix::Util::Log( radix::Error, err.source( ) ) << err.what( );
}
return 0;
}
1 #include <glPortal/Portal.hpp>
#include <algorithm>
#include <bullet/BulletDynamics/Dynamics/btRigidBody.h>
#include <bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h>
#include <radix/data/model/MeshLoader.hpp>
#include <radix/core/math/Math.hpp>
#include <radix/Entity.hpp>
#include <radix/component/Transform.hpp>
#include <radix/physics/Uncollider.hpp>
#include <radix/system/PhysicsSystem.hpp>
#include <radix/World.hpp>
using namespace radix;
namespace glPortal {
const int Portal::PORTAL_RANGE = 1000;
const Vector3f Portal::BLUE_COLOR = Vector3f( 0.33, 0.57, 1 );
const Vector3f Portal::ORANGE_COLOR = Vector3f( 1, 0.76, 0.33 );
const double Portal::NOISE_FADE_DELAY = .300;
const double Portal::OPEN_ANIM_DURATION = .250;
const float Portal::SURFACE_OFFSET = 0.01f;
26 Portal::Portal( Entity &ent ) : radix::Component( ent ), openSince( 0 ), open( false ) {
uncolliderMotionState.reset( new btDefaultMotionState );
wrapper.vertShape.reset( new btBoxShape( btVector3( 0.1, 1, 0.5 ) ) );
wrapper.horzShape.reset( new btBoxShape( btVector3( .5, 0.1, 0.5 ) ) );
// TODO Handle collision subtraction better
Uncollider::volumes.emplace_back( uncollider.get( ) );
}
34 Portal::~Portal( ) {
Uncollider::volumes.remove( uncollider.get( ) );
}
38 Vector3f Portal::getDirection( ) const {
return direction;
}
42 void Portal::placeWrapperPiece( const Vector3f &p, const Quaternion &o, const Vector3f &s,
43 const std::unique_ptr<btCollisionShape> &shape, Wrapper::Side &side, const Vector3f &offset ) {
side.motionState.reset( new btDefaultMotionState );
side.motionState->setWorldTransform(
btTransform( btQuaternion( 0, 0, 0, 1 ), p ) *
btTransform( o ) *
btTransform( btQuaternion( 0, 0, 0, 1 ), offset ) );
btRigidBody::btRigidBodyConstructionInfo ci( 0, side.motionState.get( ),
shape.get( ), btVector3( 0, 0, 0 ) );
if ( side.body ) {
entity.manager.world.systems.get<PhysicsSystem>( ).getPhysicsWorld( ).removeRigidBody( side.body.get( ) );
}
side.body.reset( new btRigidBody( ci ) );
entity.manager.world.systems.get<PhysicsSystem>( ).getPhysicsWorld( ).addRigidBody( side.body.get( ) );
}
58 void Portal::placeOnWall( const Vector3f &launchPos, const Vector3f &point, const Vector3f &normal ) {
//Determine on what side the portal is
//Side 0: -x, Side 1: x, Side 2: -z, Side 3: z, Side 4: -y, Side 5: y
/*float dist = 1000000;
int side = 0;
float *distances;
distances = PortalHelper::getDistancesForPoint( point, wall );
for ( int i = 0; i < 6; i++ ) {
if ( distances[i] < dist ) {
side = i;
dist = distances[i];
}
}*/
Transform &t = entity.getComponent<Transform>( );
Quaternion orientation;
Vector3f position( point );
Vector3f scale( 1, 2, 1 );
direction = normalize( normal );
if ( normal.fuzzyEqual( Vector3f::FORWARD ) ) {
// Edge case, since the portal has a "default normal" of 0, 0, -1
// the below quaternion-from-normal formula would be ambiguous
// and possibly fail
orientation = Quaternion( );
} else if ( normal.fuzzyEqual( Vector3f( 0, 0, 1 ) ) ) {
// Same as above, other side
orientation = Quaternion( 0, sin( M_PI/2 ), 0, cos( M_PI/2 ) );
} else if ( normal.fuzzyEqual( Vector3f( 0, 1, 0 ) ) ) {
// Floor
float yRot = std::atan2( point.x-launchPos.x, point.z-launchPos.z );
orientation.fromAero( 0, rad( 90 ), -yRot );
} else if ( normal.fuzzyEqual( Vector3f( 0, -1, 0 ) ) ) {
// Ceiling
float yRot = std::atan2( point.x-launchPos.x, point.z-launchPos.z );
orientation.fromAero( 0, rad( -90 ), yRot );
} else {
// http://www.gamedev.net/topic/566295-normal-to-a-quaternion/
const Vector3f from( 0, 0, -1 );
Vector3f H = normalize( from + normal );
orientation.w = dot( from, H );
orientation.x = from.y*H.z - from.z*H.y;
orientation.y = from.z*H.x - from.x*H.z;
orientation.z = from.x*H.y - from.y*H.x;
}
// Enable the light
// entity.getComponent<LightSource>( ).enabled = true;
placeWrapperPiece( position, orientation, scale,
wrapper.horzShape, wrapper.bottom, Vector3f( 0, -1.076, 0.501 ) );
placeWrapperPiece( position, orientation, scale,
wrapper.horzShape, wrapper.top, Vector3f( 0, 1.076, 0.501 ) );
placeWrapperPiece( position, orientation, scale,
wrapper.vertShape, wrapper.right, Vector3f( 0.576, 0, 0.501 ) );
placeWrapperPiece( position, orientation, scale,
wrapper.vertShape, wrapper.left, Vector3f( -0.576, 0, 0.501 ) );
uncolliderMotionState->setWorldTransform(
btTransform( btQuaternion( 0, 0, 0, 1 ), position ) *
btTransform( orientation ) *
btTransform( btQuaternion( 0, 0, 0, 1 ), btVector3( 0, 0, 0.499 ) ) );
uncolliderShape.reset( new btBoxShape( scale/2 ) );
btRigidBody::btRigidBodyConstructionInfo ci( 0, uncolliderMotionState.get( ),
uncolliderShape.get( ), btVector3( 0, 0, 0 ) );
uncollider.reset( new btRigidBody( ci ) );
open = true;
position += ( getDirection( ) * SURFACE_OFFSET );
overlayMesh = MeshLoader::getMesh( "Plane.obj" );
stencilMesh = MeshLoader::getMesh( "PortalStencil.obj" );
t.setPosition( position );
t.setOrientation( orientation );
t.setScale( scale );
}
136 Vector3f Portal::getScaleMult( ) const {
double delta = entity.manager.world.getTime( )-openSince;
if ( delta > OPEN_ANIM_DURATION ) {
return Vector3f( 1, 1, 1 );
}
float s = delta;
// Linear:
// std::min( ( float )delta/OPEN_ANIM_DURATION, 1.0f );
// Quadratic in/out:
s /= OPEN_ANIM_DURATION / 2;
if ( s < 1 ) {
s = 0.5f*s*s;
} else {
s--;
s = -0.5f * ( s*( s-2 ) - 1 );
}
return Vector3f( s, s, s );
}
} /* namespace glPortal */
1 #define GAME_VERSION "development"
1 #include <glPortal/World.hpp>
using namespace radix;
namespace glPortal {
7 World::World( InputSource &input ) :
radix::World( input ) {
}
11 World::~World( ) = default;
} /* namespace glPortal */
1 #include <glPortal/WorldHelper.hpp>
#include <glPortal/Portal.hpp>
#include <bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h>
#include <radix/data/texture/TextureLoader.hpp>
#include <radix/component/MeshDrawable.hpp>
#include <radix/system/PhysicsSystem.hpp>
#include <radix/component/LightSource.hpp>
using namespace radix;
namespace glPortal {
15 void WorldHelper::shootPortal( int button, World &world ) {
Vector3f cameraDir = Math::toDirection( world.camera.getOrientation( ) );
btVector3 btFrom = world.camera.getPosition( );
btVector3 btTo = btFrom + cameraDir*10000;
btCollisionWorld::ClosestRayResultCallback res( btFrom, btTo );
PhysicsSystem &phys = world.systems.get<PhysicsSystem>( );
phys.getPhysicsWorld( ).rayTest( btFrom, btTo, res );
if ( res.hasHit( ) ) {
const Entity *pEnt = reinterpret_cast<Entity*>( res.m_collisionObject->getUserPointer( ) );
// All RigidBodies should have their pointer set, but check anyway
if ( pEnt ) {
const Entity &ent = *pEnt;
// TODO: material in separate Component, + 1 mat per face
if ( ent.hasComponent<MeshDrawable>( ) and
ent.getComponent<MeshDrawable>( ).material.portalable ) {
EntityPair &pPair = getPortalPair( 0, world );
Vector3f ipos( res.m_hitPointWorld );
Entity &pEnt = ( button == 1 ) ? *pPair.first : *pPair.second;
Portal &portal = pEnt.getComponent<Portal>( );
portal.openSince = world.getTime( );
portal.maskTex.diffuse = TextureLoader::getTexture( "portalmask.png" );
portal.placeOnWall( world.camera.getPosition( ), ipos, res.m_hitNormalWorld );
LightSource &pLight = pEnt.getComponent<LightSource>( );
if ( button == 1 ) {
portal.overlayTex.diffuse = TextureLoader::getTexture( "blueportal.png" );
portal.color = pLight.color = Portal::BLUE_COLOR;
} else {
portal.overlayTex.diffuse = TextureLoader::getTexture( "orangeportal.png" );
portal.color = pLight.color = Portal::ORANGE_COLOR;
}
}
}
}
}
53 EntityPair& WorldHelper::getPortalPair( int pair, World &world ) {
return world.entityPairs.at( "portalPairs" ).at( pair );
}
57 void WorldHelper::closePortals( World &world ) {
EntityPair &pPair = getPortalPair( 0, world );
pPair.first->getComponent<Portal>( ).open = false;
pPair.second->getComponent<Portal>( ).open = false;
}
} /* namespace glPortal */
1 #include <glPortal/renderer/GameRenderer.hpp>
#include <glPortal/World.hpp>
#include <epoxy/gl.h>
#include <radix/renderer/Renderer.hpp>
#include <radix/Viewport.hpp>
#include <radix/component/ViewFrame.hpp>
#include <radix/component/MeshDrawable.hpp>
#include <radix/data/shader/ShaderLoader.hpp>
#include <radix/data/model/MeshLoader.hpp>
#include <radix/data/material/MaterialLoader.hpp>
using namespace radix;
namespace glPortal {
18 GameRenderer::GameRenderer( glPortal::World& w, radix::Renderer& ren, radix::Camera* cam, double* ptime ) :
SubRenderer( w, ren ),
camera( cam ),
dtime( ptime ){
}
24 void GameRenderer::render( ) {
time += *dtime;
renderer.getViewport( )->getSize( &viewportWidth, &viewportHeight );
glDepthMask( GL_TRUE );
glEnable( GL_DEPTH_TEST );
glEnable( GL_CULL_FACE );
glCullFace( GL_BACK );
glClearColor( 0, 0, 0, 1.0 );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
camera->setPerspective( );
camera->setAspect( ( float ) viewportWidth / viewportHeight );
renderContext->projStack.resize( 1 );
camera->getProjMatrix( renderContext->projStack.back( ) );
renderContext->viewStack.resize( 1 );
camera->getViewMatrix( renderContext->viewStack.back( ) );
renderContext->invViewStack.resize( 1 );
camera->getInvViewMatrix( renderContext->invViewStack.back( ) );
renderContext->viewFramesStack.clear( );
renderContext->projDirty = renderContext->viewDirty = true;
renderScene( *renderContext );
}
58 void GameRenderer::renderScene( RenderContext &rc ) {
if ( rc.viewFramesStack.size( ) > rc.viewStackMaxDepth ) {
return;
}
RectangleI scissor;
if ( rc.viewFramesStack.size( ) > 0 ) {
const RenderContext::ViewFrameInfo &vfi = rc.getViewFrame( );
// Don't render further if computed clip rect is zero-sized
if ( not renderer.clipViewFrame( rc, vfi.first, vfi.second, scissor ) ) {
return;
}
}
glClear( GL_DEPTH_BUFFER_BIT );
renderViewFrames( rc );
if ( rc.viewFramesStack.size( ) > 0 ) {
glScissor( scissor.x, scissor.y, scissor.w, scissor.h );
renderViewFrameStencil( rc );
}
renderEntities( rc );
}
83 void GameRenderer::renderViewFrames( RenderContext &rc ) {
GLboolean save_stencil_test;
glGetBooleanv( GL_STENCIL_TEST, &save_stencil_test );
GLboolean save_scissor_test;
glGetBooleanv( GL_SCISSOR_TEST, &save_scissor_test );
glEnable( GL_STENCIL_TEST );
glEnable( GL_SCISSOR_TEST );
for ( Entity &e : world.entityManager ) {
if ( e.hasComponent<ViewFrame>( ) ) {
const Transform &t = e.getComponent<Transform>( );
Matrix4f inMat; t.getModelMtx( inMat );
const ViewFrame &vf = e.getComponent<ViewFrame>( );
Matrix4f outMat;
outMat.translate( vf.view.getPosition( ) );
outMat.rotate( vf.view.getOrientation( ) );
Matrix4f frameView = renderer.getFrameView( rc.getView( ), inMat, outMat );
rc.pushViewFrame( RenderContext::ViewFrameInfo( vf.mesh, t ) );
rc.pushView( frameView );
renderScene( rc );
rc.popView( );
rc.popViewFrame( );
}
}
if ( not save_stencil_test ) {
glDisable( GL_STENCIL_TEST );
}
if ( not save_scissor_test ) {
glDisable( GL_SCISSOR_TEST );
}
// Draw portal in the depth buffer so they are not overwritten
glClear( GL_DEPTH_BUFFER_BIT );
GLboolean save_color_mask[4];
GLboolean save_depth_mask;
glGetBooleanv( GL_COLOR_WRITEMASK, save_color_mask );
glGetBooleanv( GL_DEPTH_WRITEMASK, &save_depth_mask );
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
glDepthMask( GL_TRUE );
Shader shader = ShaderLoader::getShader( "whitefill.frag" );
Matrix4f modelMtx;
for ( size_t i = 0; i < rc.viewFramesStack.size( ); i++ ) {
renderer.renderMesh( rc, shader, modelMtx, rc.viewFramesStack[i].first, nullptr );
}
shader.release( );
glColorMask( save_color_mask[0], save_color_mask[1], save_color_mask[2], save_color_mask[3] );
glDepthMask( save_depth_mask );
}
133 void GameRenderer::renderViewFrameStencil( RenderContext &rc ) {
GLboolean save_color_mask[4];
GLboolean save_depth_mask;
glGetBooleanv( GL_COLOR_WRITEMASK, save_color_mask );
glGetBooleanv( GL_DEPTH_WRITEMASK, &save_depth_mask );
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
glDepthMask( GL_FALSE );
glStencilFunc( GL_NEVER, 0, 0xFF );
glStencilOp( GL_INCR, GL_KEEP, GL_KEEP ); // draw 1s on test fail ( always )
glClear( GL_STENCIL_BUFFER_BIT ); // needs mask=0xFF
rc.pushView( rc.viewStack[0] );
Shader shader = ShaderLoader::getShader( "whitefill.frag" );
Matrix4f modelMtx; rc.viewFramesStack.back( ).second.getModelMtx( modelMtx );
renderer.renderMesh( rc, shader, modelMtx, rc.viewFramesStack.back( ).first, nullptr );
rc.popView( );
for ( size_t i = 1; i < rc.viewStack.size( ) - 1; i++ ) { // -1 to ignore last view
// Increment intersection for current portal
glStencilFunc( GL_EQUAL, 0, 0xFF );
glStencilOp( GL_INCR, GL_KEEP, GL_KEEP ); // draw 1s on test fail ( always )
renderer.renderMesh( rc, shader, modelMtx, rc.viewFramesStack.back( ).first, nullptr );
// Decremental outer portal -> only sub-portal intersection remains
glStencilFunc( GL_NEVER, 0, 0xFF );
glStencilOp( GL_DECR, GL_KEEP, GL_KEEP ); // draw 1s on test fail ( always )
rc.pushView( rc.viewStack[i-1] );
renderer.renderMesh( rc, shader, modelMtx, rc.viewFramesStack.back( ).first, nullptr );
}
shader.release( );
//glColorMask( GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE ); // blue-ish filter if drawing on white or grey
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
glDepthMask( GL_TRUE );
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
/* Fill 1 or more */
glStencilFunc( GL_LEQUAL, 1, 0xFF );
glColorMask( save_color_mask[0], save_color_mask[1], save_color_mask[2], save_color_mask[3] );
glDepthMask( save_depth_mask );
}
175 void GameRenderer::renderEntities( RenderContext &rc ) {
for ( Entity &e : world.entityManager ) {
if ( e.hasComponent<MeshDrawable>( ) ) {
renderEntity( rc, e );
}
}
}
183 void GameRenderer::renderEntity( RenderContext &rc, const Entity &e ) {
MeshDrawable &drawable = e.getComponent<MeshDrawable>( );
Matrix4f mtx;
e.getComponent<Transform>( ).getModelMtx( mtx );
if ( drawable.material.fancyname.compare( "Metal tiles .5x" ) == 0 ) {
Shader &metal = ShaderLoader::getShader( "metal.frag" );
renderer.renderMesh( rc, metal, mtx, drawable.mesh, drawable.material );
metal.release( );
} else {
Shader &diffuse = ShaderLoader::getShader( "diffuse.frag" );
renderer.renderMesh( rc, diffuse, mtx, drawable.mesh, drawable.material );
diffuse.release( );
}
}
199 void GameRenderer::renderPlayer( RenderContext &rc ) {
const Transform &t = world.getPlayer( ).getComponent<Transform>( );
Matrix4f mtx;
mtx.translate( t.getPosition( ) + Vector3f( 0, -.5f, 0 ) );
mtx.rotate( t.getOrientation( ) );
mtx.scale( Vector3f( 1.3f, 1.3f, 1.3f ) );
const Mesh &dummy = MeshLoader::getMesh( "HumanToken.obj" );
const Material &mat = MaterialLoader::fromTexture( "HumanToken.png" );
renderer.renderMesh( rc, ShaderLoader::getShader( "diffuse.frag" ), mtx, dummy, mat );
}
211 void GameRenderer::setCameraInPortal( const Camera &cam, Camera &dest,
212 const Entity &portal, const Entity &otherPortal ) {
Transform &p1T = portal.getComponent<Transform>( );
Matrix4f p1mat;
p1mat.translate( p1T.getPosition( ) );
p1mat.rotate( p1T.getOrientation( ) );
Transform &p2T = otherPortal.getComponent<Transform>( );
Matrix4f p2mat;
p2mat.translate( p2T.getPosition( ) );
p2mat.rotate( p2T.getOrientation( ) );
Matrix4f rotate180; rotate180.rotate( rad( 180 ), 0, 1, 0 );
Matrix4f view; cam.getViewMatrix( view );
Matrix4f destView = view * p1mat * rotate180 * inverse( p2mat );
dest.setPerspective( );
dest.setAspect( cam.getAspect( ) );
dest.setFovy( cam.getFovy( ) );
dest.setZNear( ( p1T.getPosition( ) - cam.getPosition( ) ).length( ) );
dest.setViewMatrix( destView );
}
} /* namespace glPortal */
1 #include <glPortal/renderer/TerminalRenderer.hpp>
#include <glPortal/component/Terminal.hpp>
#include <epoxy/gl.h>
#include <radix/renderer/Renderer.hpp>
#include <radix/data/model/MeshLoader.hpp>
#include <radix/data/shader/ShaderLoader.hpp>
#include <radix/Viewport.hpp>
using namespace radix;
namespace glPortal {
15 void TerminalRenderer::render( RenderContext &rc, World &world ) {
int vpWidth, vpHeight;
Renderer &renderer = rc.renderer;
renderer.getViewport( )->getSize( &vpWidth, &vpHeight );
Camera camera;
camera.setOrthographic( );
camera.setBounds( 0, vpWidth, 0, vpHeight );
rc.pushCamera( camera );
Matrix4f widget;
widget.translate( Vector3f( vpWidth/2, vpHeight-100, -5 ) );
widget.scale( Vector3f( vpWidth, 200, 1 ) );
const Mesh &mesh = MeshLoader::getMesh( "GUIElement.obj" );
Shader &sh = ShaderLoader::getShader( "color.frag" );
Terminal &term = world.entityAliases.at( "activeTerminal" )->getComponent<Terminal>( );
Vector4f screenBackgroundColor = term.backgroundColor;
sh.bind( );
glUniform4f( sh.uni( "color" ),
screenBackgroundColor.x,
screenBackgroundColor.y,
screenBackgroundColor.z,
screenBackgroundColor.w );
renderer.renderMesh( rc, sh, widget, mesh, nullptr );
Text terminalText;
terminalText.font = "Pacaya";
terminalText.size = 1.0f;
terminalText.content = world.input.getCharBuffer( );
terminalText.color = term.textColor;
terminalText.position = Vector3f( 0, vpHeight-30, -1 );
renderer.renderText( rc, terminalText );
sh.release( );
rc.popCamera( );
}
} /* namespace glPortal */
1 #include <glPortal/renderer/UiRenderer.hpp>
#include <glPortal/Game.hpp>
#include <epoxy/gl.h>
#include <radix/data/model/MeshLoader.hpp>
#include <radix/data/shader/ShaderLoader.hpp>
#include <radix/data/material/MaterialLoader.hpp>
#include "../Version.hpp"
using namespace radix;
namespace glPortal {
16 UiRenderer::UiRenderer( World &w, radix::Renderer &ren ) :
SubRenderer( w, ren ) {
}
21 void UiRenderer::render( ) {
glDepthMask( GL_FALSE );
renderer.getViewport( )->getSize( &viewportWidth, &viewportHeight );
initCamera( );
// Hand
renderImage( Vector3f( viewportWidth - 400, 250, -50 ), Vector3f( 960, 540, 1 ), "hand.png" );
// Crosshair
renderImage( Vector3f( viewportWidth / 2, viewportHeight / 2, -10 ), Vector3f( 80, 80, 1 ), "Reticle.png" );
Text glPortalTitle;
glPortalTitle.font = "Pacaya";
glPortalTitle.size = 1.5f;
glPortalTitle.content = "GlPortal";
glPortalTitle.color = Vector4f( 1, 1, 1, 1 );
glPortalTitle.position = Vector3f( 25, viewportHeight - 95, -20 );
renderer.renderText( *renderContext.get( ), glPortalTitle );
Text fpsCounter;
fpsCounter.font = "Pacaya";
fpsCounter.size = 0.5f;
fpsCounter.content = std::string( "FPS: " ) + std::to_string( Game::fps.getFps( ) );
fpsCounter.color = Vector4f( 1, 1, 1, 1 );
fpsCounter.position = Vector3f( 10, viewportHeight - 25, -20 );
renderer.renderText( *renderContext.get( ), fpsCounter );
Text version;
version.font = "Pacaya";
version.size = 0.5f;
version.content = std::string( "Early testing build: " ) + GAME_VERSION;
version.color = Vector4f( 1, 1, 1, 1 );
version.position = Vector3f( 10, viewportHeight - 45, -20 );
renderer.renderText( *renderContext.get( ), version );
renderContext->popCamera( );
glDepthMask( GL_TRUE );
}
62 void UiRenderer::renderImage( radix::Vector3f position, radix::Vector3f scale, std::string path ) {
Matrix4f matrix;
matrix.translate( position );
matrix.scale( scale );
const Mesh &mesh = MeshLoader::getMesh( "GUIElement.obj" );
const Material &material = MaterialLoader::fromTexture( path );
Shader &sh = ShaderLoader::getShader( "unshaded.frag" );
renderer.renderMesh( *renderContext.get( ), sh, matrix, mesh, material );
sh.release( );
}
} /* namespace glPortal */
1 #include <glPortal/system/PortalSystem.hpp>
#include <glPortal/Portal.hpp>
#include <radix/component/Player.hpp>
#include <radix/physics/PhysicsHelper.hpp>
#include <radix/World.hpp>
using namespace radix;
namespace glPortal {
12 PortalSystem::PortalSystem( World &w ) :
System( w ) {
}
16 PortalSystem::~PortalSystem( ) {
}
19 void PortalSystem::update( float dtime ) {
( void ) dtime;
for ( Entity &e : world.entityManager ) {
if ( e.hasComponent<Player>( ) ) {
Transform &t = e.getComponent<Transform>( );
const Vector3f &pos = t.getPosition( );
Player &plr = e.getComponent<Player>( );
for ( const EntityPair &pp : world.entityPairs.at( "portals" ) ) {
btVector3 min, max;
Portal &pA = pp.first->getComponent<Portal>( ),
&pB = pp.second->getComponent<Portal>( );
// No uncollider? No portal link.
if ( not pA.uncollider or not pB.uncollider ) {
continue;
}
pA.uncolliderShape->getAabb(
pA.uncollider->getWorldTransform( ),
min, max );
// Is player within portal A uncollider ( AABB then real check ) ?
if ( PhysicsHelper::pointInAABB( pos, min, max ) and
PhysicsHelper::pointInVolume( pos, *pA.uncollider ) ) {
// Behind portal A
const Transform
&pAT = pp.first->getComponent<Transform>( ),
&pBT = pp.second->getComponent<Transform>( );
Vector3f normalA = pA.getDirection( );
Vector3f AP = pos - pAT.getPosition( );
if ( dot( AP, normalA ) < 0 ) {
Matrix4f rotate180; rotate180.rotate( rad( 180 ), 0, 1, 0 );
Matrix4f view = inverse( plr.getBaseHeadOrientation( ).toMatrix( ) );
view.translate( -t.getPosition( ) );
Matrix4f iv = inverse( view *
Matrix4f( pAT.getPosition( ), pAT.getOrientation( ) ) *
rotate180 *
inverse( Matrix4f( pBT.getPosition( ), pBT.getOrientation( ) ) ) );
t.setPosition( iv.getPosition( ) );
plr.headAngle = iv.getRotation( ).toAero( );
}
}
pB.uncolliderShape->getAabb(
pB.uncollider->getWorldTransform( ),
min, max );
// Is player within portal B uncollider ?
if ( PhysicsHelper::pointInAABB( pos, min, max ) and
PhysicsHelper::pointInVolume( pos, *pB.uncollider ) ) {
// Behind portal B
const Transform
&pAT = pp.first->getComponent<Transform>( ),
&pBT = pp.second->getComponent<Transform>( );
Vector3f normalB = pB.getDirection( );
Vector3f BP = pos - pBT.getPosition( );
if ( dot( BP, normalB ) < 0 ) {
Matrix4f rotate180; rotate180.rotate( rad( 180 ), 0, 1, 0 );
Matrix4f view = inverse( plr.getBaseHeadOrientation( ).toMatrix( ) );
view.translate( -t.getPosition( ) );
Matrix4f iv = inverse( view *
Matrix4f( pBT.getPosition( ), pBT.getOrientation( ) ) *
rotate180 *
inverse( Matrix4f( pAT.getPosition( ), pAT.getOrientation( ) ) ) );
t.setPosition( Vector3f( iv[12], iv[13], iv[14] ) );
plr.headAngle = iv.getRotation( ).toAero( );
}
}
}
}
}
}
} /* namespace glPortal */