mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 23:19:19 +02:00
build 181030. basic external views system
This commit is contained in:
132
Camera.cpp
132
Camera.cpp
@@ -14,44 +14,30 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
#include "Console.h"
|
#include "Console.h"
|
||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
|
#include "DynObj.h"
|
||||||
#include "MOVER.h"
|
#include "MOVER.h"
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void TCamera::Init( Math3D::vector3 const &NPos, Math3D::vector3 const &NAngle, TCameraType const NType ) {
|
void TCamera::Init( Math3D::vector3 const &NPos, Math3D::vector3 const &NAngle/*, TCameraType const NType*/, TDynamicObject *Owner ) {
|
||||||
|
|
||||||
vUp = { 0, 1, 0 };
|
vUp = { 0, 1, 0 };
|
||||||
Velocity = { 0, 0, 0 };
|
Velocity = { 0, 0, 0 };
|
||||||
Pitch = NAngle.x;
|
Angle = NAngle;
|
||||||
Yaw = NAngle.y;
|
|
||||||
Roll = NAngle.z;
|
|
||||||
Pos = NPos;
|
Pos = NPos;
|
||||||
|
|
||||||
Type = NType;
|
m_owner = Owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
void TCamera::Reset() {
|
void TCamera::Reset() {
|
||||||
|
|
||||||
Pitch = Yaw = Roll = 0;
|
Angle = {};
|
||||||
m_rotationoffsets = {};
|
m_rotationoffsets = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void TCamera::OnCursorMove(double x, double y) {
|
void TCamera::OnCursorMove(double x, double y) {
|
||||||
/*
|
|
||||||
Yaw -= x;
|
|
||||||
while( Yaw > M_PI ) {
|
|
||||||
Yaw -= 2 * M_PI;
|
|
||||||
}
|
|
||||||
while( Yaw < -M_PI ) {
|
|
||||||
Yaw += 2 * M_PI;
|
|
||||||
}
|
|
||||||
Pitch -= y;
|
|
||||||
if (Type == tp_Follow) {
|
|
||||||
// jeżeli jazda z pojazdem ograniczenie kąta spoglądania w dół i w górę
|
|
||||||
Pitch = clamp( Pitch, -M_PI_4, M_PI_4 );
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
m_rotationoffsets += glm::dvec3 { y, x, 0.0 };
|
m_rotationoffsets += glm::dvec3 { y, x, 0.0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,19 +62,21 @@ TCamera::OnCommand( command_data const &Command ) {
|
|||||||
case user_command::movehorizontalfast: {
|
case user_command::movehorizontalfast: {
|
||||||
|
|
||||||
auto const movespeed = (
|
auto const movespeed = (
|
||||||
Type == TCameraType::tp_Free ? runspeed :
|
m_owner == nullptr ? runspeed : // free roam
|
||||||
Type == TCameraType::tp_Follow ? walkspeed :
|
false == FreeFlyModeFlag ? walkspeed : // vehicle cab
|
||||||
0.0 );
|
0.0 ); // vehicle external
|
||||||
|
|
||||||
|
// if( movespeed == 0.0 ) { break; } // enable to fix external cameras in place
|
||||||
|
|
||||||
auto const speedmultiplier = (
|
auto const speedmultiplier = (
|
||||||
( ( Type == TCameraType::tp_Free ) && ( Command.command == user_command::movehorizontalfast ) ) ?
|
( ( m_owner == nullptr ) && ( Command.command == user_command::movehorizontalfast ) ) ?
|
||||||
30.0 :
|
30.0 :
|
||||||
1.0 );
|
1.0 );
|
||||||
|
|
||||||
// left-right
|
// left-right
|
||||||
auto const movexparam { Command.param1 };
|
auto const movexparam { Command.param1 };
|
||||||
// 2/3rd of the stick range enables walk speed, past that we lerp between walk and run speed
|
// 2/3rd of the stick range enables walk speed, past that we lerp between walk and run speed
|
||||||
auto const movex { walkspeed + ( std::max( 0.0, std::abs( movexparam ) - 0.65 ) / 0.35 ) * ( movespeed - walkspeed ) };
|
auto const movex { walkspeed + ( std::max( 0.0, std::abs( movexparam ) - 0.65 ) / 0.35 ) * std::max( 0.0, movespeed - walkspeed ) };
|
||||||
|
|
||||||
m_moverate.x = (
|
m_moverate.x = (
|
||||||
movexparam > 0.0 ? movex * speedmultiplier :
|
movexparam > 0.0 ? movex * speedmultiplier :
|
||||||
@@ -97,7 +85,7 @@ TCamera::OnCommand( command_data const &Command ) {
|
|||||||
|
|
||||||
// forward-back
|
// forward-back
|
||||||
double const movezparam { Command.param2 };
|
double const movezparam { Command.param2 };
|
||||||
auto const movez { walkspeed + ( std::max( 0.0, std::abs( movezparam ) - 0.65 ) / 0.35 ) * ( movespeed - walkspeed ) };
|
auto const movez { walkspeed + ( std::max( 0.0, std::abs( movezparam ) - 0.65 ) / 0.35 ) * std::max( 0.0, movespeed - walkspeed ) };
|
||||||
// NOTE: z-axis is flipped given world coordinate system
|
// NOTE: z-axis is flipped given world coordinate system
|
||||||
m_moverate.z = (
|
m_moverate.z = (
|
||||||
movezparam > 0.0 ? -movez * speedmultiplier :
|
movezparam > 0.0 ? -movez * speedmultiplier :
|
||||||
@@ -111,15 +99,16 @@ TCamera::OnCommand( command_data const &Command ) {
|
|||||||
case user_command::moveverticalfast: {
|
case user_command::moveverticalfast: {
|
||||||
|
|
||||||
auto const movespeed = (
|
auto const movespeed = (
|
||||||
Type == TCameraType::tp_Free ? runspeed * 0.5 :
|
m_owner == nullptr ? runspeed * 0.5 : // free roam
|
||||||
Type == TCameraType::tp_Follow ? walkspeed :
|
false == FreeFlyModeFlag ? walkspeed : // vehicle cab
|
||||||
0.0 );
|
0.0 ); // vehicle external
|
||||||
|
|
||||||
|
// if( movespeed == 0.0 ) { break; } // enable to fix external cameras in place
|
||||||
|
|
||||||
auto const speedmultiplier = (
|
auto const speedmultiplier = (
|
||||||
( ( Type == TCameraType::tp_Free ) && ( Command.command == user_command::moveverticalfast ) ) ?
|
( ( m_owner == nullptr ) && ( Command.command == user_command::moveverticalfast ) ) ?
|
||||||
10.0 :
|
10.0 :
|
||||||
1.0 );
|
1.0 );
|
||||||
|
|
||||||
// up-down
|
// up-down
|
||||||
auto const moveyparam { Command.param1 };
|
auto const moveyparam { Command.param1 };
|
||||||
// 2/3rd of the stick range enables walk speed, past that we lerp between walk and run speed
|
// 2/3rd of the stick range enables walk speed, past that we lerp between walk and run speed
|
||||||
@@ -145,9 +134,6 @@ TCamera::OnCommand( command_data const &Command ) {
|
|||||||
|
|
||||||
void TCamera::Update()
|
void TCamera::Update()
|
||||||
{
|
{
|
||||||
if( FreeFlyModeFlag == true ) { Type = TCameraType::tp_Free; }
|
|
||||||
else { Type = TCameraType::tp_Follow; }
|
|
||||||
|
|
||||||
// check for sent user commands
|
// check for sent user commands
|
||||||
// NOTE: this is a temporary arrangement, for the transition period from old command setup to the new one
|
// NOTE: this is a temporary arrangement, for the transition period from old command setup to the new one
|
||||||
// ultimately we'll need to track position of camera/driver for all human entities present in the scenario
|
// ultimately we'll need to track position of camera/driver for all human entities present in the scenario
|
||||||
@@ -161,8 +147,28 @@ void TCamera::Update()
|
|||||||
|
|
||||||
auto const deltatime { Timer::GetDeltaRenderTime() }; // czas bez pauzy
|
auto const deltatime { Timer::GetDeltaRenderTime() }; // czas bez pauzy
|
||||||
|
|
||||||
|
// update rotation
|
||||||
|
auto const rotationfactor { std::min( 1.0, 20 * deltatime ) };
|
||||||
|
|
||||||
|
Angle.y -= m_rotationoffsets.y * rotationfactor;
|
||||||
|
m_rotationoffsets.y *= ( 1.0 - rotationfactor );
|
||||||
|
while( Angle.y > M_PI ) {
|
||||||
|
Angle.y -= 2 * M_PI;
|
||||||
|
}
|
||||||
|
while( Angle.y < -M_PI ) {
|
||||||
|
Angle.y += 2 * M_PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
Angle.x -= m_rotationoffsets.x * rotationfactor;
|
||||||
|
m_rotationoffsets.x *= ( 1.0 - rotationfactor );
|
||||||
|
|
||||||
|
if( m_owner != nullptr ) {
|
||||||
|
// jeżeli jazda z pojazdem ograniczenie kąta spoglądania w dół i w górę
|
||||||
|
Angle.x = clamp( Angle.x, -M_PI_4, M_PI_4 );
|
||||||
|
}
|
||||||
|
|
||||||
// update position
|
// update position
|
||||||
if( ( Type == TCameraType::tp_Free )
|
if( ( m_owner == nullptr )
|
||||||
|| ( false == Global.ctrlState )
|
|| ( false == Global.ctrlState )
|
||||||
|| ( true == DebugCameraFlag ) ) {
|
|| ( true == DebugCameraFlag ) ) {
|
||||||
// ctrl is used for mirror view, so we ignore the controls when in vehicle if ctrl is pressed
|
// ctrl is used for mirror view, so we ignore the controls when in vehicle if ctrl is pressed
|
||||||
@@ -171,46 +177,34 @@ void TCamera::Update()
|
|||||||
Velocity.z = clamp( Velocity.z + m_moverate.z * 10.0 * deltatime, -std::abs( m_moverate.z ), std::abs( m_moverate.z ) );
|
Velocity.z = clamp( Velocity.z + m_moverate.z * 10.0 * deltatime, -std::abs( m_moverate.z ), std::abs( m_moverate.z ) );
|
||||||
Velocity.y = clamp( Velocity.y + m_moverate.y * 10.0 * deltatime, -std::abs( m_moverate.y ), std::abs( m_moverate.y ) );
|
Velocity.y = clamp( Velocity.y + m_moverate.y * 10.0 * deltatime, -std::abs( m_moverate.y ), std::abs( m_moverate.y ) );
|
||||||
}
|
}
|
||||||
|
if( ( m_owner == nullptr )
|
||||||
if( ( Type == TCameraType::tp_Free )
|
|
||||||
|| ( true == DebugCameraFlag ) ) {
|
|| ( true == DebugCameraFlag ) ) {
|
||||||
// free movement position update is handled here, movement while in vehicle is handled by train update
|
// free movement position update
|
||||||
Math3D::vector3 Vec = Velocity;
|
auto movement { Velocity };
|
||||||
Vec.RotateY( Yaw );
|
movement.RotateY( Angle.y );
|
||||||
Pos += Vec * 5.0 * deltatime;
|
Pos += movement * 5.0 * deltatime;
|
||||||
}
|
}
|
||||||
// update rotation
|
else {
|
||||||
auto const rotationfactor { std::min( 1.0, 20 * deltatime ) };
|
// attached movement position update
|
||||||
|
auto movement { Velocity * -2.0 };
|
||||||
|
movement.y = -movement.y;
|
||||||
|
if( m_owner->MoverParameters->ActiveCab < 0 ) {
|
||||||
|
movement *= -1.f;
|
||||||
|
movement.y = -movement.y;
|
||||||
|
}
|
||||||
|
movement.RotateY( Angle.y );
|
||||||
|
|
||||||
Yaw -= rotationfactor * m_rotationoffsets.y;
|
m_owneroffset += movement * deltatime;
|
||||||
m_rotationoffsets.y *= ( 1.0 - rotationfactor );
|
|
||||||
while( Yaw > M_PI ) {
|
|
||||||
Yaw -= 2 * M_PI;
|
|
||||||
}
|
}
|
||||||
while( Yaw < -M_PI ) {
|
|
||||||
Yaw += 2 * M_PI;
|
|
||||||
}
|
|
||||||
|
|
||||||
Pitch -= rotationfactor * m_rotationoffsets.x;
|
|
||||||
m_rotationoffsets.x *= ( 1.0 - rotationfactor );
|
|
||||||
if( Type == TCameraType::tp_Follow ) {
|
|
||||||
// jeżeli jazda z pojazdem ograniczenie kąta spoglądania w dół i w górę
|
|
||||||
Pitch = clamp( Pitch, -M_PI_4, M_PI_4 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Math3D::vector3 TCamera::GetDirection() {
|
|
||||||
|
|
||||||
return glm::normalize( glm::rotateY<float>( glm::vec3{ 0.f, 0.f, 1.f }, Yaw ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TCamera::SetMatrix( glm::dmat4 &Matrix ) {
|
bool TCamera::SetMatrix( glm::dmat4 &Matrix ) {
|
||||||
|
|
||||||
Matrix = glm::rotate( Matrix, -Roll, glm::dvec3( 0.0, 0.0, 1.0 ) ); // po wyłączeniu tego kręci się pojazd, a sceneria nie
|
Matrix = glm::rotate( Matrix, -Angle.z, glm::dvec3( 0.0, 0.0, 1.0 ) ); // po wyłączeniu tego kręci się pojazd, a sceneria nie
|
||||||
Matrix = glm::rotate( Matrix, -Pitch, glm::dvec3( 1.0, 0.0, 0.0 ) );
|
Matrix = glm::rotate( Matrix, -Angle.x, glm::dvec3( 1.0, 0.0, 0.0 ) );
|
||||||
Matrix = glm::rotate( Matrix, -Yaw, glm::dvec3( 0.0, 1.0, 0.0 ) ); // w zewnętrznym widoku: kierunek patrzenia
|
Matrix = glm::rotate( Matrix, -Angle.y, glm::dvec3( 0.0, 1.0, 0.0 ) ); // w zewnętrznym widoku: kierunek patrzenia
|
||||||
|
|
||||||
if( ( Type == TCameraType::tp_Follow ) && ( false == DebugCameraFlag ) ) {
|
if( ( m_owner != nullptr ) && ( false == DebugCameraFlag ) ) {
|
||||||
|
|
||||||
Matrix *= glm::lookAt(
|
Matrix *= glm::lookAt(
|
||||||
glm::dvec3{ Pos },
|
glm::dvec3{ Pos },
|
||||||
@@ -226,14 +220,14 @@ bool TCamera::SetMatrix( glm::dmat4 &Matrix ) {
|
|||||||
|
|
||||||
void TCamera::RaLook()
|
void TCamera::RaLook()
|
||||||
{ // zmiana kierunku patrzenia - przelicza Yaw
|
{ // zmiana kierunku patrzenia - przelicza Yaw
|
||||||
Math3D::vector3 where = LookAt - Pos + Math3D::vector3(0, 3, 0); // trochę w górę od szyn
|
Math3D::vector3 where = LookAt - Pos /*+ Math3D::vector3(0, 3, 0)*/; // trochę w górę od szyn
|
||||||
if( ( where.x != 0.0 ) || ( where.z != 0.0 ) ) {
|
if( ( where.x != 0.0 ) || ( where.z != 0.0 ) ) {
|
||||||
Yaw = atan2( -where.x, -where.z ); // kąt horyzontalny
|
Angle.y = atan2( -where.x, -where.z ); // kąt horyzontalny
|
||||||
m_rotationoffsets.y = 0.0;
|
m_rotationoffsets.y = 0.0;
|
||||||
}
|
}
|
||||||
double l = Math3D::Length3(where);
|
double l = Math3D::Length3(where);
|
||||||
if( l > 0.0 ) {
|
if( l > 0.0 ) {
|
||||||
Pitch = asin( where.y / l ); // kąt w pionie
|
Angle.x = asin( where.y / l ); // kąt w pionie
|
||||||
m_rotationoffsets.x = 0.0;
|
m_rotationoffsets.x = 0.0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
17
Camera.h
17
Camera.h
@@ -13,34 +13,27 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "command.h"
|
#include "command.h"
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
enum class TCameraType
|
|
||||||
{ // tryby pracy kamery
|
|
||||||
tp_Follow, // jazda z pojazdem
|
|
||||||
tp_Free, // stoi na scenerii
|
|
||||||
tp_Satelite // widok z góry (nie używany)
|
|
||||||
};
|
|
||||||
|
|
||||||
class TCamera {
|
class TCamera {
|
||||||
|
|
||||||
public: // McZapkie: potrzebuje do kiwania na boki
|
public: // McZapkie: potrzebuje do kiwania na boki
|
||||||
void Init( Math3D::vector3 const &Location, Math3D::vector3 const &Angle, TCameraType const Type );
|
void Init( Math3D::vector3 const &Location, Math3D::vector3 const &Angle, TDynamicObject *Owner );
|
||||||
void Reset();
|
void Reset();
|
||||||
void OnCursorMove(double const x, double const y);
|
void OnCursorMove(double const x, double const y);
|
||||||
bool OnCommand( command_data const &Command );
|
bool OnCommand( command_data const &Command );
|
||||||
void Update();
|
void Update();
|
||||||
Math3D::vector3 GetDirection();
|
|
||||||
bool SetMatrix(glm::dmat4 &Matrix);
|
bool SetMatrix(glm::dmat4 &Matrix);
|
||||||
void RaLook();
|
void RaLook();
|
||||||
|
|
||||||
TCameraType Type;
|
Math3D::vector3 Angle; // pitch, yaw, roll
|
||||||
double Pitch;
|
|
||||||
double Yaw; // w środku: 0=do przodu; na zewnątrz: 0=na południe
|
|
||||||
double Roll;
|
|
||||||
Math3D::vector3 Pos; // współrzędne obserwatora
|
Math3D::vector3 Pos; // współrzędne obserwatora
|
||||||
Math3D::vector3 LookAt; // współrzędne punktu, na który ma patrzeć
|
Math3D::vector3 LookAt; // współrzędne punktu, na który ma patrzeć
|
||||||
Math3D::vector3 vUp;
|
Math3D::vector3 vUp;
|
||||||
Math3D::vector3 Velocity;
|
Math3D::vector3 Velocity;
|
||||||
|
|
||||||
|
TDynamicObject *m_owner { nullptr }; // TODO: change to const when shake calculations are part of vehicles update
|
||||||
|
Math3D::vector3 m_owneroffset {};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
glm::dvec3 m_moverate;
|
glm::dvec3 m_moverate;
|
||||||
glm::dvec3 m_rotationoffsets; // requested changes to pitch, yaw and roll
|
glm::dvec3 m_rotationoffsets; // requested changes to pitch, yaw and roll
|
||||||
|
|||||||
2
Driver.h
2
Driver.h
@@ -428,4 +428,6 @@ private:
|
|||||||
return iDirection; }
|
return iDirection; }
|
||||||
TDynamicObject const *Vehicle() const {
|
TDynamicObject const *Vehicle() const {
|
||||||
return pVehicle; }
|
return pVehicle; }
|
||||||
|
TDynamicObject *Vehicle( side const Side ) const {
|
||||||
|
return pVehicles[ Side ]; }
|
||||||
};
|
};
|
||||||
|
|||||||
143
DynObj.cpp
143
DynObj.cpp
@@ -2109,6 +2109,10 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
|
|||||||
|
|
||||||
create_controller( DriverType, !TrainName.empty() );
|
create_controller( DriverType, !TrainName.empty() );
|
||||||
|
|
||||||
|
ShakeSpring.Init( 125.0 );
|
||||||
|
BaseShake = baseshake_config {};
|
||||||
|
ShakeState = shake_state {};
|
||||||
|
|
||||||
// McZapkie-250202
|
// McZapkie-250202
|
||||||
/*
|
/*
|
||||||
iAxles = std::min( MoverParameters->NAxles, MaxAxles ); // ilość osi
|
iAxles = std::min( MoverParameters->NAxles, MaxAxles ); // ilość osi
|
||||||
@@ -4403,7 +4407,8 @@ void TDynamicObject::RenderSounds() {
|
|||||||
0.0, 1.0,
|
0.0, 1.0,
|
||||||
clamp(
|
clamp(
|
||||||
MoverParameters->Vel / 40.0,
|
MoverParameters->Vel / 40.0,
|
||||||
0.0, 1.0 ) );
|
0.0, 1.0 ) )
|
||||||
|
+ ( MyTrack->eType == tt_Switch ? 0.25 : 0.0 );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
volume = 0;
|
volume = 0;
|
||||||
@@ -5855,6 +5860,46 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
|||||||
m_startjolt.owner( this );
|
m_startjolt.owner( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (token == "mechspring:")
|
||||||
|
{
|
||||||
|
// parametry bujania kamery:
|
||||||
|
double ks, kd;
|
||||||
|
parser.getTokens(2, false);
|
||||||
|
parser
|
||||||
|
>> ks
|
||||||
|
>> kd;
|
||||||
|
ShakeSpring.Init(ks, kd);
|
||||||
|
parser.getTokens(6, false);
|
||||||
|
parser
|
||||||
|
>> BaseShake.jolt_scale.x
|
||||||
|
>> BaseShake.jolt_scale.y
|
||||||
|
>> BaseShake.jolt_scale.z
|
||||||
|
>> BaseShake.jolt_limit
|
||||||
|
>> BaseShake.angle_scale.x
|
||||||
|
>> BaseShake.angle_scale.z;
|
||||||
|
}
|
||||||
|
else if( token == "enginespring:" ) {
|
||||||
|
parser.getTokens( 5, false );
|
||||||
|
parser
|
||||||
|
>> EngineShake.scale
|
||||||
|
>> EngineShake.fadein_offset
|
||||||
|
>> EngineShake.fadein_factor
|
||||||
|
>> EngineShake.fadeout_offset
|
||||||
|
>> EngineShake.fadeout_factor;
|
||||||
|
// offsets values are provided as rpm for convenience
|
||||||
|
EngineShake.fadein_offset /= 60.f;
|
||||||
|
EngineShake.fadeout_offset /= 60.f;
|
||||||
|
}
|
||||||
|
else if( token == "huntingspring:" ) {
|
||||||
|
parser.getTokens( 4, false );
|
||||||
|
parser
|
||||||
|
>> HuntingShake.scale
|
||||||
|
>> HuntingShake.frequency
|
||||||
|
>> HuntingShake.fadein_begin
|
||||||
|
>> HuntingShake.fadein_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} while( token != "" );
|
} while( token != "" );
|
||||||
|
|
||||||
} // internaldata:
|
} // internaldata:
|
||||||
@@ -6468,6 +6513,102 @@ TDynamicObject::ConnectedEnginePowerSource( TDynamicObject const *Caller ) const
|
|||||||
return MoverParameters->EnginePowerSource.SourceType;
|
return MoverParameters->EnginePowerSource.SourceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TDynamicObject::update_shake( double const Timedelta ) {
|
||||||
|
// Ra: mechanik powinien być telepany niezależnie od pozycji pojazdu
|
||||||
|
// Ra: trzeba zrobić model bujania głową i wczepić go do pojazdu
|
||||||
|
|
||||||
|
// Ra: tu by się przydało uwzględnić rozkład sił:
|
||||||
|
// - na postoju horyzont prosto, kabina skosem
|
||||||
|
// - przy szybkiej jeździe kabina prosto, horyzont pochylony
|
||||||
|
|
||||||
|
// McZapkie: najpierw policzę pozycję w/m kabiny
|
||||||
|
|
||||||
|
// ABu: rzucamy kabina tylko przy duzym FPS!
|
||||||
|
// Mala histereza, zeby bez przerwy nie przelaczalo przy FPS~17
|
||||||
|
// Granice mozna ustalic doswiadczalnie. Ja proponuje 14:20
|
||||||
|
if( false == Global.iSlowMotion ) { // musi być pełna prędkość
|
||||||
|
|
||||||
|
Math3D::vector3 shakevector;
|
||||||
|
if( ( MoverParameters->EngineType == TEngineType::DieselElectric )
|
||||||
|
|| ( MoverParameters->EngineType == TEngineType::DieselEngine ) ) {
|
||||||
|
if( std::abs( MoverParameters->enrot ) > 0.0 ) {
|
||||||
|
// engine vibration
|
||||||
|
shakevector.x +=
|
||||||
|
( std::sin( MoverParameters->eAngle * 4.0 ) * Timedelta * EngineShake.scale )
|
||||||
|
// fade in with rpm above threshold
|
||||||
|
* clamp(
|
||||||
|
( MoverParameters->enrot - EngineShake.fadein_offset ) * EngineShake.fadein_factor,
|
||||||
|
0.0, 1.0 )
|
||||||
|
// fade out with rpm above threshold
|
||||||
|
* interpolate(
|
||||||
|
1.0, 0.0,
|
||||||
|
clamp(
|
||||||
|
( MoverParameters->enrot - EngineShake.fadeout_offset ) * EngineShake.fadeout_factor,
|
||||||
|
0.0, 1.0 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( HuntingShake.fadein_begin > 0.f )
|
||||||
|
&& ( true == MoverParameters->TruckHunting ) ) {
|
||||||
|
// hunting oscillation
|
||||||
|
HuntingAngle = clamp_circular( HuntingAngle + 4.0 * HuntingShake.frequency * Timedelta * MoverParameters->Vel, 360.0 );
|
||||||
|
auto const huntingamount =
|
||||||
|
interpolate(
|
||||||
|
0.0, 1.0,
|
||||||
|
clamp(
|
||||||
|
( MoverParameters->Vel - HuntingShake.fadein_begin ) / ( HuntingShake.fadein_end - HuntingShake.fadein_begin ),
|
||||||
|
0.0, 1.0 ) );
|
||||||
|
shakevector.x +=
|
||||||
|
( std::sin( glm::radians( HuntingAngle ) ) * Timedelta * HuntingShake.scale )
|
||||||
|
* huntingamount;
|
||||||
|
IsHunting = ( huntingamount > 0.025 );
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const iVel { std::min( GetVelocity(), 150.0 ) };
|
||||||
|
if( iVel > 0.5 ) {
|
||||||
|
// acceleration-driven base shake
|
||||||
|
shakevector += Math3D::vector3(
|
||||||
|
-MoverParameters->AccN * Timedelta * 5.0, // highlight side sway
|
||||||
|
-MoverParameters->AccVert * Timedelta,
|
||||||
|
-MoverParameters->AccSVBased * Timedelta * 1.25 ); // accent acceleration/deceleration
|
||||||
|
}
|
||||||
|
|
||||||
|
auto shake { 1.25 * ShakeSpring.ComputateForces( shakevector, ShakeState.offset ) };
|
||||||
|
|
||||||
|
if( Random( iVel ) > 25.0 ) {
|
||||||
|
// extra shake at increased velocity
|
||||||
|
shake += ShakeSpring.ComputateForces(
|
||||||
|
Math3D::vector3(
|
||||||
|
( Random( iVel * 2 ) - iVel ) / ( ( iVel * 2 ) * 4 ) * BaseShake.jolt_scale.x,
|
||||||
|
( Random( iVel * 2 ) - iVel ) / ( ( iVel * 2 ) * 4 ) * BaseShake.jolt_scale.y,
|
||||||
|
( Random( iVel * 2 ) - iVel ) / ( ( iVel * 2 ) * 4 ) * BaseShake.jolt_scale.z )
|
||||||
|
// * (( 200 - DynamicObject->MyTrack->iQualityFlag ) * 0.0075 ) // scale to 75-150% based on track quality
|
||||||
|
* 1.25,
|
||||||
|
ShakeState.offset );
|
||||||
|
}
|
||||||
|
shake *= 0.85;
|
||||||
|
|
||||||
|
ShakeState.velocity -= ( shake + ShakeState.velocity * 100 ) * ( BaseShake.jolt_scale.x + BaseShake.jolt_scale.y + BaseShake.jolt_scale.z ) / ( 200 );
|
||||||
|
|
||||||
|
// McZapkie:
|
||||||
|
ShakeState.offset += ShakeState.velocity * Timedelta;
|
||||||
|
if( std::abs( ShakeState.offset.y ) > std::abs( BaseShake.jolt_limit ) ) {
|
||||||
|
ShakeState.velocity.y = -ShakeState.velocity.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // hamowanie rzucania przy spadku FPS
|
||||||
|
ShakeState.offset -= ShakeState.offset * std::min( Timedelta, 1.0 ); // po tym chyba potrafią zostać jakieś ułamki, które powodują zjazd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<double, double>
|
||||||
|
TDynamicObject::shake_angles() const {
|
||||||
|
|
||||||
|
return {
|
||||||
|
std::atan( ShakeState.velocity.x * BaseShake.angle_scale.x ),
|
||||||
|
std::atan( ShakeState.velocity.z * BaseShake.angle_scale.z ) };
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TDynamicObject::powertrain_sounds::position( glm::vec3 const Location ) {
|
TDynamicObject::powertrain_sounds::position( glm::vec3 const Location ) {
|
||||||
|
|||||||
41
DynObj.h
41
DynObj.h
@@ -19,6 +19,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "Button.h"
|
#include "Button.h"
|
||||||
#include "AirCoupler.h"
|
#include "AirCoupler.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
|
#include "Spring.h"
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -444,8 +445,6 @@ private:
|
|||||||
exchange_data m_exchange; // state of active load exchange procedure, if any
|
exchange_data m_exchange; // state of active load exchange procedure, if any
|
||||||
exchange_sounds m_exchangesounds; // sounds associated with the load exchange
|
exchange_sounds m_exchangesounds; // sounds associated with the load exchange
|
||||||
|
|
||||||
Math3D::vector3 modelShake;
|
|
||||||
|
|
||||||
bool renderme; // yB - czy renderowac
|
bool renderme; // yB - czy renderowac
|
||||||
float ModCamRot;
|
float ModCamRot;
|
||||||
int iInventory[ 2 ] { 0, 0 }; // flagi bitowe posiadanych submodeli (np. świateł)
|
int iInventory[ 2 ] { 0, 0 }; // flagi bitowe posiadanych submodeli (np. świateł)
|
||||||
@@ -540,6 +539,9 @@ private:
|
|||||||
void RenderSounds();
|
void RenderSounds();
|
||||||
inline Math3D::vector3 GetPosition() const {
|
inline Math3D::vector3 GetPosition() const {
|
||||||
return vPosition; };
|
return vPosition; };
|
||||||
|
// converts location from vehicle coordinates frame to world frame
|
||||||
|
inline Math3D::vector3 GetWorldPosition( Math3D::vector3 const &Location ) const {
|
||||||
|
return vPosition + mMatrix * Location; }
|
||||||
// pobranie współrzędnych czoła
|
// pobranie współrzędnych czoła
|
||||||
inline Math3D::vector3 HeadPosition() {
|
inline Math3D::vector3 HeadPosition() {
|
||||||
return vCoulpler[iDirection ^ 1]; };
|
return vCoulpler[iDirection ^ 1]; };
|
||||||
@@ -638,6 +640,41 @@ private:
|
|||||||
double MEDLogTime = 0;
|
double MEDLogTime = 0;
|
||||||
double MEDLogInactiveTime = 0;
|
double MEDLogInactiveTime = 0;
|
||||||
int MEDLogCount = 0;
|
int MEDLogCount = 0;
|
||||||
|
|
||||||
|
// vehicle shaking calculations
|
||||||
|
// TBD, TODO: make an object out of it
|
||||||
|
public:
|
||||||
|
// methods
|
||||||
|
void update_shake( double const Timedelta );
|
||||||
|
std::pair<double, double> shake_angles() const;
|
||||||
|
// members
|
||||||
|
struct baseshake_config {
|
||||||
|
Math3D::vector3 angle_scale { 0.05, 0.0, 0.1 }; // roll, yaw, pitch
|
||||||
|
Math3D::vector3 jolt_scale { 0.2, 0.2, 0.1 };
|
||||||
|
double jolt_limit { 0.15 };
|
||||||
|
} BaseShake;
|
||||||
|
struct engineshake_config {
|
||||||
|
float scale { 2.f };
|
||||||
|
float fadein_offset { 1.5f }; // 90 rpm
|
||||||
|
float fadein_factor { 0.3f };
|
||||||
|
float fadeout_offset { 10.f }; // 600 rpm
|
||||||
|
float fadeout_factor { 0.5f };
|
||||||
|
} EngineShake;
|
||||||
|
struct huntingshake_config {
|
||||||
|
float scale { 1.f };
|
||||||
|
float frequency { 1.f };
|
||||||
|
float fadein_begin { 0.f }; // effect start speed in km/h
|
||||||
|
float fadein_end { 0.f }; // full effect speed in km/h
|
||||||
|
} HuntingShake;
|
||||||
|
float HuntingAngle { 0.f }; // crude approximation of hunting oscillation; current angle of sine wave
|
||||||
|
bool IsHunting { false };
|
||||||
|
TSpring ShakeSpring;
|
||||||
|
struct shake_state {
|
||||||
|
Math3D::vector3 velocity {}; // current shaking vector
|
||||||
|
Math3D::vector3 offset {}; // overall shake-driven offset from base position
|
||||||
|
} ShakeState;
|
||||||
|
|
||||||
|
Math3D::vector3 modelShake;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
235
Train.cpp
235
Train.cpp
@@ -365,8 +365,6 @@ TTrain::TTrain() {
|
|||||||
fPPress = fNPress = 0;
|
fPPress = fNPress = 0;
|
||||||
|
|
||||||
// asMessage="";
|
// asMessage="";
|
||||||
pMechShake = Math3D::vector3(0, 0, 0);
|
|
||||||
vMechMovement = Math3D::vector3(0, 0, 0);
|
|
||||||
pMechOffset = Math3D::vector3(0, 0, 0);
|
pMechOffset = Math3D::vector3(0, 0, 0);
|
||||||
fBlinkTimer = 0;
|
fBlinkTimer = 0;
|
||||||
fHaslerTimer = 0;
|
fHaslerTimer = 0;
|
||||||
@@ -415,15 +413,6 @@ bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d)
|
|||||||
|
|
||||||
DynamicObject->MechInside = true;
|
DynamicObject->MechInside = true;
|
||||||
|
|
||||||
MechSpring.Init(125.0);
|
|
||||||
vMechVelocity = Math3D::vector3(0, 0, 0);
|
|
||||||
pMechOffset = Math3D::vector3( 0, 0, 0 );
|
|
||||||
fMechSpringX = 0.2;
|
|
||||||
fMechSpringY = 0.2;
|
|
||||||
fMechSpringZ = 0.1;
|
|
||||||
fMechMaxSpring = 0.15;
|
|
||||||
fMechRoll = 0.05;
|
|
||||||
fMechPitch = 0.1;
|
|
||||||
fMainRelayTimer = 0; // Hunter, do k...y nędzy, ustawiaj wartości początkowe zmiennych!
|
fMainRelayTimer = 0; // Hunter, do k...y nędzy, ustawiaj wartości początkowe zmiennych!
|
||||||
|
|
||||||
if( false == LoadMMediaFile( DynamicObject->asBaseDir + DynamicObject->MoverParameters->TypeName + ".mmd" ) ) {
|
if( false == LoadMMediaFile( DynamicObject->asBaseDir + DynamicObject->MoverParameters->TypeName + ".mmd" ) ) {
|
||||||
@@ -4708,138 +4697,25 @@ void TTrain::OnCommand_cabchangebackward( TTrain *Train, command_data const &Com
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cab movement update, fixed step part
|
// cab movement update, fixed step part
|
||||||
void TTrain::UpdateMechPosition(double dt)
|
void TTrain::UpdateCab() {
|
||||||
{ // Ra: mechanik powinien być telepany niezależnie od pozycji pojazdu
|
|
||||||
// Ra: trzeba zrobić model bujania głową i wczepić go do pojazdu
|
|
||||||
|
|
||||||
// DynamicObject->vFront=DynamicObject->GetDirection(); //to jest już policzone
|
// Ra: przesiadka, jeśli AI zmieniło kabinę (a człon?)...
|
||||||
|
if( ( DynamicObject->Mechanik ) // może nie być?
|
||||||
|
&& ( DynamicObject->Mechanik->AIControllFlag ) ) {
|
||||||
|
|
||||||
|
if( iCabn != ( // numer kabiny (-1: kabina B)
|
||||||
|
DynamicObject->MoverParameters->ActiveCab == -1 ?
|
||||||
|
2 :
|
||||||
|
DynamicObject->MoverParameters->ActiveCab ) ) {
|
||||||
|
|
||||||
// Ra: tu by się przydało uwzględnić rozkład sił:
|
InitializeCab(
|
||||||
// - na postoju horyzont prosto, kabina skosem
|
DynamicObject->MoverParameters->ActiveCab,
|
||||||
// - przy szybkiej jeździe kabina prosto, horyzont pochylony
|
DynamicObject->asBaseDir + DynamicObject->MoverParameters->TypeName + ".mmd" );
|
||||||
|
|
||||||
Math3D::vector3 shake;
|
|
||||||
// McZapkie: najpierw policzę pozycję w/m kabiny
|
|
||||||
|
|
||||||
// ABu: rzucamy kabina tylko przy duzym FPS!
|
|
||||||
// Mala histereza, zeby bez przerwy nie przelaczalo przy FPS~17
|
|
||||||
// Granice mozna ustalic doswiadczalnie. Ja proponuje 14:20
|
|
||||||
double const iVel = std::min( DynamicObject->GetVelocity(), 150.0 );
|
|
||||||
|
|
||||||
if( ( false == Global.iSlowMotion ) // musi być pełna prędkość
|
|
||||||
&& ( pMechOffset.y < 4.0 ) ) // Ra 15-01: przy oglądaniu pantografu bujanie przeszkadza
|
|
||||||
{
|
|
||||||
Math3D::vector3 shakevector;
|
|
||||||
if( ( mvOccupied->EngineType == TEngineType::DieselElectric )
|
|
||||||
|| ( mvOccupied->EngineType == TEngineType::DieselEngine ) ) {
|
|
||||||
if( std::abs( mvOccupied->enrot ) > 0.0 ) {
|
|
||||||
// engine vibration
|
|
||||||
shakevector.x +=
|
|
||||||
( std::sin( mvOccupied->eAngle * 4.0 ) * dt * EngineShake.scale )
|
|
||||||
// fade in with rpm above threshold
|
|
||||||
* clamp(
|
|
||||||
( mvOccupied->enrot - EngineShake.fadein_offset ) * EngineShake.fadein_factor,
|
|
||||||
0.0, 1.0 )
|
|
||||||
// fade out with rpm above threshold
|
|
||||||
* interpolate(
|
|
||||||
1.0, 0.0,
|
|
||||||
clamp(
|
|
||||||
( mvOccupied->enrot - EngineShake.fadeout_offset ) * EngineShake.fadeout_factor,
|
|
||||||
0.0, 1.0 ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ( HuntingShake.fadein_begin > 0.f )
|
|
||||||
&& ( true == mvOccupied->TruckHunting ) ) {
|
|
||||||
// hunting oscillation
|
|
||||||
HuntingAngle = clamp_circular( HuntingAngle + 4.0 * HuntingShake.frequency * dt * mvOccupied->Vel, 360.0 );
|
|
||||||
auto const huntingamount =
|
|
||||||
interpolate(
|
|
||||||
0.0, 1.0,
|
|
||||||
clamp(
|
|
||||||
( mvOccupied->Vel - HuntingShake.fadein_begin ) / ( HuntingShake.fadein_end - HuntingShake.fadein_begin ),
|
|
||||||
0.0, 1.0 ) );
|
|
||||||
shakevector.x +=
|
|
||||||
( std::sin( glm::radians( HuntingAngle ) ) * dt * HuntingShake.scale )
|
|
||||||
* huntingamount;
|
|
||||||
IsHunting = ( huntingamount > 0.025 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( iVel > 0.5 ) {
|
|
||||||
// acceleration-driven base shake
|
|
||||||
shakevector += Math3D::vector3(
|
|
||||||
-mvOccupied->AccN * dt * 5.0, // highlight side sway
|
|
||||||
-mvOccupied->AccVert * dt,
|
|
||||||
-mvOccupied->AccSVBased * dt * 1.25 ); // accent acceleration/deceleration
|
|
||||||
}
|
|
||||||
|
|
||||||
shake += 1.25 * MechSpring.ComputateForces( shakevector, pMechShake );
|
|
||||||
|
|
||||||
if( Random( iVel ) > 25.0 ) {
|
|
||||||
// extra shake at increased velocity
|
|
||||||
shake += MechSpring.ComputateForces(
|
|
||||||
Math3D::vector3(
|
|
||||||
( Random( iVel * 2 ) - iVel ) / ( ( iVel * 2 ) * 4 ) * fMechSpringX,
|
|
||||||
( Random( iVel * 2 ) - iVel ) / ( ( iVel * 2 ) * 4 ) * fMechSpringY,
|
|
||||||
( Random( iVel * 2 ) - iVel ) / ( ( iVel * 2 ) * 4 ) * fMechSpringZ )
|
|
||||||
* 1.25,
|
|
||||||
pMechShake );
|
|
||||||
// * (( 200 - DynamicObject->MyTrack->iQualityFlag ) * 0.0075 ); // scale to 75-150% based on track quality
|
|
||||||
}
|
|
||||||
shake *= 0.85;
|
|
||||||
|
|
||||||
vMechVelocity -= ( shake + vMechVelocity * 100 ) * ( fMechSpringX + fMechSpringY + fMechSpringZ ) / ( 200 );
|
|
||||||
|
|
||||||
// McZapkie:
|
|
||||||
pMechShake += vMechVelocity * dt;
|
|
||||||
if( ( pMechShake.y > fMechMaxSpring )
|
|
||||||
|| ( pMechShake.y < -fMechMaxSpring ) ) {
|
|
||||||
vMechVelocity.y = -vMechVelocity.y;
|
|
||||||
}
|
|
||||||
// Ra 2015-01: dotychczasowe rzucanie
|
|
||||||
pMechOffset += vMechMovement * dt;
|
|
||||||
// ABu011104: 5*pMechShake.y, zeby ladnie pudlem rzucalo :)
|
|
||||||
pMechPosition = pMechOffset + Math3D::vector3( 1.5 * pMechShake.x, 2.0 * pMechShake.y, 1.5 * pMechShake.z );
|
|
||||||
}
|
}
|
||||||
else { // hamowanie rzucania przy spadku FPS
|
|
||||||
pMechShake -= pMechShake * std::min( dt, 1.0 ); // po tym chyba potrafią zostać jakieś ułamki, które powodują zjazd
|
|
||||||
pMechOffset += vMechMovement * dt;
|
|
||||||
vMechVelocity.y = 0.5 * vMechVelocity.y;
|
|
||||||
pMechPosition = pMechOffset + Math3D::vector3( pMechShake.x, 5 * pMechShake.y, pMechShake.z );
|
|
||||||
}
|
|
||||||
// numer kabiny (-1: kabina B)
|
|
||||||
if( DynamicObject->Mechanik ) // może nie być?
|
|
||||||
if( DynamicObject->Mechanik->AIControllFlag ) // jeśli prowadzi AI
|
|
||||||
{ // Ra: przesiadka, jeśli AI zmieniło kabinę (a człon?)...
|
|
||||||
if( iCabn != ( DynamicObject->MoverParameters->ActiveCab == -1 ?
|
|
||||||
2 :
|
|
||||||
DynamicObject->MoverParameters->ActiveCab ) )
|
|
||||||
InitializeCab( DynamicObject->MoverParameters->ActiveCab,
|
|
||||||
DynamicObject->asBaseDir + DynamicObject->MoverParameters->TypeName +
|
|
||||||
".mmd" );
|
|
||||||
}
|
|
||||||
iCabn = ( DynamicObject->MoverParameters->ActiveCab == -1 ?
|
iCabn = ( DynamicObject->MoverParameters->ActiveCab == -1 ?
|
||||||
2 :
|
2 :
|
||||||
DynamicObject->MoverParameters->ActiveCab );
|
DynamicObject->MoverParameters->ActiveCab );
|
||||||
if( !DebugModeFlag ) { // sprawdzaj więzy //Ra: nie tu!
|
|
||||||
|
|
||||||
pMechPosition.x = clamp( pMechPosition.x, Cabine[ iCabn ].CabPos1.x, Cabine[ iCabn ].CabPos2.x );
|
|
||||||
pMechPosition.y = clamp( pMechPosition.y, Cabine[ iCabn ].CabPos1.y + 0.5, Cabine[ iCabn ].CabPos2.y + 1.8 );
|
|
||||||
pMechPosition.z = clamp( pMechPosition.z, Cabine[ iCabn ].CabPos1.z, Cabine[ iCabn ].CabPos2.z );
|
|
||||||
|
|
||||||
pMechOffset.x = clamp( pMechOffset.x, Cabine[ iCabn ].CabPos1.x, Cabine[ iCabn ].CabPos2.x );
|
|
||||||
pMechOffset.y = clamp( pMechOffset.y, Cabine[ iCabn ].CabPos1.y + 0.5, Cabine[ iCabn ].CabPos2.y + 1.8 );
|
|
||||||
pMechOffset.z = clamp( pMechOffset.z, Cabine[ iCabn ].CabPos1.z, Cabine[ iCabn ].CabPos2.z );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// returns position of the mechanic in the scene coordinates
|
|
||||||
Math3D::vector3
|
|
||||||
TTrain::GetWorldMechPosition() {
|
|
||||||
|
|
||||||
auto position = DynamicObject->mMatrix * pMechPosition; // położenie względem środka pojazdu w układzie scenerii
|
|
||||||
position += DynamicObject->GetPosition();
|
|
||||||
return position;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TTrain::Update( double const Deltatime )
|
bool TTrain::Update( double const Deltatime )
|
||||||
@@ -4920,17 +4796,7 @@ bool TTrain::Update( double const Deltatime )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update driver's position
|
UpdateCab();
|
||||||
{
|
|
||||||
auto Vec = Global.pCamera.Velocity * -2.0;// -7.5 * Timer::GetDeltaRenderTime();
|
|
||||||
Vec.y = -Vec.y;
|
|
||||||
if( mvOccupied->ActiveCab < 0 ) {
|
|
||||||
Vec *= -1.0f;
|
|
||||||
Vec.y = -Vec.y;
|
|
||||||
}
|
|
||||||
Vec.RotateY( Global.pCamera.Yaw );
|
|
||||||
vMechMovement = Vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DynamicObject->mdKabina)
|
if (DynamicObject->mdKabina)
|
||||||
{ // Ra: TODO: odczyty klawiatury/pulpitu nie powinny być uzależnione od istnienia modelu kabiny
|
{ // Ra: TODO: odczyty klawiatury/pulpitu nie powinny być uzależnione od istnienia modelu kabiny
|
||||||
@@ -6169,7 +6035,7 @@ TTrain::update_sounds( double const Deltatime ) {
|
|||||||
if( ( false == FreeFlyModeFlag )
|
if( ( false == FreeFlyModeFlag )
|
||||||
&& ( false == Global.CabWindowOpen )
|
&& ( false == Global.CabWindowOpen )
|
||||||
&& ( DynamicObject->GetVelocity() > 0.5 )
|
&& ( DynamicObject->GetVelocity() > 0.5 )
|
||||||
&& ( IsHunting ) ) {
|
&& ( DynamicObject->IsHunting ) ) {
|
||||||
|
|
||||||
update_sounds_runningnoise( rsHuntingNoise );
|
update_sounds_runningnoise( rsHuntingNoise );
|
||||||
// modify calculated sound volume by hunting amount
|
// modify calculated sound volume by hunting amount
|
||||||
@@ -6177,7 +6043,7 @@ TTrain::update_sounds( double const Deltatime ) {
|
|||||||
interpolate(
|
interpolate(
|
||||||
0.0, 1.0,
|
0.0, 1.0,
|
||||||
clamp(
|
clamp(
|
||||||
( mvOccupied->Vel - HuntingShake.fadein_begin ) / ( HuntingShake.fadein_end - HuntingShake.fadein_begin ),
|
( mvOccupied->Vel - DynamicObject->HuntingShake.fadein_begin ) / ( DynamicObject->HuntingShake.fadein_end - DynamicObject->HuntingShake.fadein_begin ),
|
||||||
0.0, 1.0 ) );
|
0.0, 1.0 ) );
|
||||||
|
|
||||||
rsHuntingNoise.gain( rsHuntingNoise.gain() * huntingamount );
|
rsHuntingNoise.gain( rsHuntingNoise.gain() * huntingamount );
|
||||||
@@ -6489,44 +6355,6 @@ bool TTrain::LoadMMediaFile(std::string const &asFileName)
|
|||||||
rsHuntingNoise.m_amplitudefactor /= ( 1 + mvOccupied->Vmax );
|
rsHuntingNoise.m_amplitudefactor /= ( 1 + mvOccupied->Vmax );
|
||||||
rsHuntingNoise.m_frequencyfactor /= ( 1 + mvOccupied->Vmax );
|
rsHuntingNoise.m_frequencyfactor /= ( 1 + mvOccupied->Vmax );
|
||||||
}
|
}
|
||||||
else if (token == "mechspring:")
|
|
||||||
{
|
|
||||||
// parametry bujania kamery:
|
|
||||||
double ks, kd;
|
|
||||||
parser.getTokens(2, false);
|
|
||||||
parser
|
|
||||||
>> ks
|
|
||||||
>> kd;
|
|
||||||
MechSpring.Init(ks, kd);
|
|
||||||
parser.getTokens(6, false);
|
|
||||||
parser
|
|
||||||
>> fMechSpringX
|
|
||||||
>> fMechSpringY
|
|
||||||
>> fMechSpringZ
|
|
||||||
>> fMechMaxSpring
|
|
||||||
>> fMechRoll
|
|
||||||
>> fMechPitch;
|
|
||||||
}
|
|
||||||
else if( token == "enginespring:" ) {
|
|
||||||
parser.getTokens( 5, false );
|
|
||||||
parser
|
|
||||||
>> EngineShake.scale
|
|
||||||
>> EngineShake.fadein_offset
|
|
||||||
>> EngineShake.fadein_factor
|
|
||||||
>> EngineShake.fadeout_offset
|
|
||||||
>> EngineShake.fadeout_factor;
|
|
||||||
// offsets values are provided as rpm for convenience
|
|
||||||
EngineShake.fadein_offset /= 60.f;
|
|
||||||
EngineShake.fadeout_offset /= 60.f;
|
|
||||||
}
|
|
||||||
else if( token == "huntingspring:" ) {
|
|
||||||
parser.getTokens( 4, false );
|
|
||||||
parser
|
|
||||||
>> HuntingShake.scale
|
|
||||||
>> HuntingShake.frequency
|
|
||||||
>> HuntingShake.fadein_begin
|
|
||||||
>> HuntingShake.fadein_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
} while (token != "");
|
} while (token != "");
|
||||||
}
|
}
|
||||||
@@ -6571,8 +6399,6 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
|
|||||||
}
|
}
|
||||||
// reset view angles
|
// reset view angles
|
||||||
pMechViewAngle = { 0.0, 0.0 };
|
pMechViewAngle = { 0.0, 0.0 };
|
||||||
Global.pCamera.Pitch = pMechViewAngle.x;
|
|
||||||
Global.pCamera.Yaw = pMechViewAngle.y;
|
|
||||||
bool parse = false;
|
bool parse = false;
|
||||||
int cabindex = 0;
|
int cabindex = 0;
|
||||||
DynamicObject->mdKabina = NULL; // likwidacja wskaźnika na dotychczasową kabinę
|
DynamicObject->mdKabina = NULL; // likwidacja wskaźnika na dotychczasową kabinę
|
||||||
@@ -6670,9 +6496,10 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
|
|||||||
>> viewangle.y // yaw first, then pitch
|
>> viewangle.y // yaw first, then pitch
|
||||||
>> viewangle.x;
|
>> viewangle.x;
|
||||||
pMechViewAngle = glm::radians( viewangle );
|
pMechViewAngle = glm::radians( viewangle );
|
||||||
|
/*
|
||||||
Global.pCamera.Pitch = pMechViewAngle.x;
|
Global.pCamera.Pitch = pMechViewAngle.x;
|
||||||
Global.pCamera.Yaw = pMechViewAngle.y;
|
Global.pCamera.Yaw = pMechViewAngle.y;
|
||||||
|
*/
|
||||||
parser.getTokens();
|
parser.getTokens();
|
||||||
parser >> token;
|
parser >> token;
|
||||||
}
|
}
|
||||||
@@ -6862,14 +6689,6 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
|
|||||||
return (token == "none");
|
return (token == "none");
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTrain::MechStop()
|
|
||||||
{ // likwidacja ruchu kamery w kabinie (po powrocie przez [F4])
|
|
||||||
pMechPosition = Math3D::vector3(0, 0, 0);
|
|
||||||
pMechShake = Math3D::vector3(0, 0, 0);
|
|
||||||
vMechMovement = Math3D::vector3(0, 0, 0);
|
|
||||||
vMechVelocity = Math3D::vector3(0, 0, 0); // tu zostawały jakieś ułamki, powodujące uciekanie kamery
|
|
||||||
};
|
|
||||||
|
|
||||||
Math3D::vector3 TTrain::MirrorPosition(bool lewe)
|
Math3D::vector3 TTrain::MirrorPosition(bool lewe)
|
||||||
{ // zwraca współrzędne widoku kamery z lusterka
|
{ // zwraca współrzędne widoku kamery z lusterka
|
||||||
switch (iCabn)
|
switch (iCabn)
|
||||||
@@ -6947,6 +6766,26 @@ void TTrain::DynamicSet(TDynamicObject *d)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// checks whether specified point is within boundaries of the active cab
|
||||||
|
bool
|
||||||
|
TTrain::point_inside( Math3D::vector3 const Point ) const {
|
||||||
|
|
||||||
|
return ( Point.x >= Cabine[ iCabn ].CabPos1.x ) && ( Point.x <= Cabine[ iCabn ].CabPos2.x )
|
||||||
|
&& ( Point.y >= Cabine[ iCabn ].CabPos1.y + 0.5 ) && ( Point.y <= Cabine[ iCabn ].CabPos2.y + 1.8 )
|
||||||
|
&& ( Point.z >= Cabine[ iCabn ].CabPos1.z ) && ( Point.z <= Cabine[ iCabn ].CabPos2.z );
|
||||||
|
}
|
||||||
|
|
||||||
|
Math3D::vector3
|
||||||
|
TTrain::clamp_inside( Math3D::vector3 const &Point ) const {
|
||||||
|
|
||||||
|
if( DebugModeFlag ) { return Point; }
|
||||||
|
|
||||||
|
return {
|
||||||
|
clamp( Point.x, Cabine[ iCabn ].CabPos1.x, Cabine[ iCabn ].CabPos2.x ),
|
||||||
|
clamp( Point.y, Cabine[ iCabn ].CabPos1.y + 0.5, Cabine[ iCabn ].CabPos2.y + 1.8 ),
|
||||||
|
clamp( Point.z, Cabine[ iCabn ].CabPos1.z, Cabine[ iCabn ].CabPos2.z ) };
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TTrain::radio_message( sound_source *Message, int const Channel ) {
|
TTrain::radio_message( sound_source *Message, int const Channel ) {
|
||||||
|
|
||||||
|
|||||||
49
Train.h
49
Train.h
@@ -13,7 +13,6 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "DynObj.h"
|
#include "DynObj.h"
|
||||||
#include "Button.h"
|
#include "Button.h"
|
||||||
#include "Gauge.h"
|
#include "Gauge.h"
|
||||||
#include "Spring.h"
|
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#include "PyInt.h"
|
#include "PyInt.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
@@ -105,10 +104,8 @@ class TTrain
|
|||||||
inline Math3D::vector3 GetDirection() { return DynamicObject->VectorFront(); };
|
inline Math3D::vector3 GetDirection() { return DynamicObject->VectorFront(); };
|
||||||
inline Math3D::vector3 GetUp() { return DynamicObject->VectorUp(); };
|
inline Math3D::vector3 GetUp() { return DynamicObject->VectorUp(); };
|
||||||
inline std::string GetLabel( TSubModel const *Control ) const { return m_controlmapper.find( Control ); }
|
inline std::string GetLabel( TSubModel const *Control ) const { return m_controlmapper.find( Control ); }
|
||||||
void UpdateMechPosition(double dt);
|
void UpdateCab();
|
||||||
Math3D::vector3 GetWorldMechPosition();
|
|
||||||
bool Update( double const Deltatime );
|
bool Update( double const Deltatime );
|
||||||
void MechStop();
|
|
||||||
void SetLights();
|
void SetLights();
|
||||||
// McZapkie-310302: ladowanie parametrow z pliku
|
// McZapkie-310302: ladowanie parametrow z pliku
|
||||||
bool LoadMMediaFile(std::string const &asFileName);
|
bool LoadMMediaFile(std::string const &asFileName);
|
||||||
@@ -565,40 +562,6 @@ public: // reszta może by?publiczna
|
|||||||
// Ra 2013-12: wirtualne "lampki" do odbijania na haslerze w PoKeys
|
// Ra 2013-12: wirtualne "lampki" do odbijania na haslerze w PoKeys
|
||||||
TButton btHaslerBrakes; // ciśnienie w cylindrach
|
TButton btHaslerBrakes; // ciśnienie w cylindrach
|
||||||
TButton btHaslerCurrent; // prąd na silnikach
|
TButton btHaslerCurrent; // prąd na silnikach
|
||||||
/*
|
|
||||||
vector3 pPosition;
|
|
||||||
*/
|
|
||||||
Math3D::vector3 pMechOffset; // driverNpos
|
|
||||||
Math3D::vector3 vMechMovement;
|
|
||||||
Math3D::vector3 pMechPosition;
|
|
||||||
Math3D::vector3 pMechShake;
|
|
||||||
Math3D::vector3 vMechVelocity;
|
|
||||||
// McZapkie: do poruszania sie po kabinie
|
|
||||||
// McZapkie: opis kabiny - obszar poruszania sie mechanika oraz zajetosc
|
|
||||||
TCab Cabine[maxcab + 1]; // przedzial maszynowy, kabina 1 (A), kabina 2 (B)
|
|
||||||
int iCabn;
|
|
||||||
TSpring MechSpring;
|
|
||||||
double fMechSpringX; // McZapkie-250303: parametry bujania
|
|
||||||
double fMechSpringY;
|
|
||||||
double fMechSpringZ;
|
|
||||||
double fMechMaxSpring;
|
|
||||||
double fMechRoll;
|
|
||||||
double fMechPitch;
|
|
||||||
struct engineshake_config {
|
|
||||||
float scale { 2.f };
|
|
||||||
float fadein_offset { 1.5f }; // 90 rpm
|
|
||||||
float fadein_factor { 0.3f };
|
|
||||||
float fadeout_offset { 10.f }; // 600 rpm
|
|
||||||
float fadeout_factor { 0.5f };
|
|
||||||
} EngineShake;
|
|
||||||
struct huntingshake_config {
|
|
||||||
float scale { 1.f };
|
|
||||||
float frequency { 1.f };
|
|
||||||
float fadein_begin { 0.f }; // effect start speed in km/h
|
|
||||||
float fadein_end { 0.f }; // full effect speed in km/h
|
|
||||||
} HuntingShake;
|
|
||||||
float HuntingAngle { 0.f }; // crude approximation of hunting oscillation; current angle of sine wave
|
|
||||||
bool IsHunting { false };
|
|
||||||
|
|
||||||
sound_source dsbReverserKey { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // hunter-121211
|
sound_source dsbReverserKey { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // hunter-121211
|
||||||
sound_source dsbNastawnikJazdy { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
|
sound_source dsbNastawnikJazdy { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
|
||||||
@@ -631,8 +594,13 @@ public: // reszta może by?publiczna
|
|||||||
bool bCabLight; // hunter-091012: czy swiatlo jest zapalone?
|
bool bCabLight; // hunter-091012: czy swiatlo jest zapalone?
|
||||||
bool bCabLightDim; // hunter-091012: czy przyciemnienie kabiny jest zapalone?
|
bool bCabLightDim; // hunter-091012: czy przyciemnienie kabiny jest zapalone?
|
||||||
|
|
||||||
|
// McZapkie: opis kabiny - obszar poruszania sie mechanika oraz zajetosc
|
||||||
|
TCab Cabine[ maxcab + 1 ]; // przedzial maszynowy, kabina 1 (A), kabina 2 (B)
|
||||||
|
int iCabn;
|
||||||
|
// McZapkie: do poruszania sie po kabinie
|
||||||
Math3D::vector3 pMechSittingPosition; // ABu 180404
|
Math3D::vector3 pMechSittingPosition; // ABu 180404
|
||||||
Math3D::vector3 MirrorPosition(bool lewe);
|
Math3D::vector3 MirrorPosition( bool lewe );
|
||||||
|
Math3D::vector3 pMechOffset; // base position of the driver in the cab
|
||||||
glm::vec2 pMechViewAngle { 0.0, 0.0 }; // camera pitch and yaw values, preserved while in external view
|
glm::vec2 pMechViewAngle { 0.0, 0.0 }; // camera pitch and yaw values, preserved while in external view
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -687,6 +655,9 @@ private:
|
|||||||
inline TMoverParameters *Occupied() { return mvOccupied; };
|
inline TMoverParameters *Occupied() { return mvOccupied; };
|
||||||
inline TMoverParameters const *Occupied() const { return mvOccupied; };
|
inline TMoverParameters const *Occupied() const { return mvOccupied; };
|
||||||
void DynamicSet(TDynamicObject *d);
|
void DynamicSet(TDynamicObject *d);
|
||||||
|
// checks whether specified point is within boundaries of the active cab
|
||||||
|
bool point_inside( Math3D::vector3 const Point ) const;
|
||||||
|
Math3D::vector3 clamp_inside( Math3D::vector3 const &Point ) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
400
drivermode.cpp
400
drivermode.cpp
@@ -165,12 +165,9 @@ driver_mode::update() {
|
|||||||
iPause = Global.iPause;
|
iPause = Global.iPause;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fixed step part of the camera update
|
// TODO: generic shake update pass for vehicles within view range
|
||||||
if( ( simulation::Train != nullptr )
|
if( Camera.m_owner != nullptr ) {
|
||||||
&& ( Camera.Type == TCameraType::tp_Follow )
|
Camera.m_owner->update_shake( m_secondaryupdaterate );
|
||||||
&& ( false == DebugCameraFlag ) ) {
|
|
||||||
// jeśli jazda w kabinie, przeliczyć trzeba parametry kamery
|
|
||||||
simulation::Train->UpdateMechPosition( m_secondaryupdaterate );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_secondaryupdateaccumulator -= m_secondaryupdaterate; // these should be inexpensive enough we have no cap
|
m_secondaryupdateaccumulator -= m_secondaryupdaterate; // these should be inexpensive enough we have no cap
|
||||||
@@ -247,15 +244,15 @@ driver_mode::update() {
|
|||||||
void
|
void
|
||||||
driver_mode::enter() {
|
driver_mode::enter() {
|
||||||
|
|
||||||
Camera.Init(Global.FreeCameraInit[0], Global.FreeCameraInitAngle[0], ( FreeFlyModeFlag ? TCameraType::tp_Free : TCameraType::tp_Follow ) );
|
|
||||||
Global.pCamera = Camera;
|
|
||||||
Global.pDebugCamera = DebugCamera;
|
|
||||||
|
|
||||||
TDynamicObject *nPlayerTrain { (
|
TDynamicObject *nPlayerTrain { (
|
||||||
( Global.asHumanCtrlVehicle != "ghostview" ) ?
|
( Global.asHumanCtrlVehicle != "ghostview" ) ?
|
||||||
simulation::Vehicles.find( Global.asHumanCtrlVehicle ) :
|
simulation::Vehicles.find( Global.asHumanCtrlVehicle ) :
|
||||||
nullptr ) };
|
nullptr ) };
|
||||||
|
|
||||||
|
Camera.Init(Global.FreeCameraInit[0], Global.FreeCameraInitAngle[0], nPlayerTrain );
|
||||||
|
Global.pCamera = Camera;
|
||||||
|
Global.pDebugCamera = DebugCamera;
|
||||||
|
|
||||||
if (nPlayerTrain)
|
if (nPlayerTrain)
|
||||||
{
|
{
|
||||||
WriteLog( "Initializing player train, \"" + Global.asHumanCtrlVehicle + "\"" );
|
WriteLog( "Initializing player train, \"" + Global.asHumanCtrlVehicle + "\"" );
|
||||||
@@ -269,14 +266,14 @@ driver_mode::enter() {
|
|||||||
|
|
||||||
Application.set_title( Global.AppName + " (" + simulation::Train->Controlled()->Name + " @ " + Global.SceneryFile + ")" );
|
Application.set_title( Global.AppName + " (" + simulation::Train->Controlled()->Name + " @ " + Global.SceneryFile + ")" );
|
||||||
|
|
||||||
FollowView();
|
CabView();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Error("Bad init: player train initialization failed");
|
Error("Bad init: player train initialization failed");
|
||||||
FreeFlyModeFlag = true; // Ra: automatycznie włączone latanie
|
FreeFlyModeFlag = true; // Ra: automatycznie włączone latanie
|
||||||
SafeDelete( simulation::Train );
|
SafeDelete( simulation::Train );
|
||||||
Camera.Type = TCameraType::tp_Free;
|
Camera.m_owner = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -286,7 +283,7 @@ driver_mode::enter() {
|
|||||||
Error("Bad scenario: failed to locate player train, \"" + Global.asHumanCtrlVehicle + "\"" );
|
Error("Bad scenario: failed to locate player train, \"" + Global.asHumanCtrlVehicle + "\"" );
|
||||||
}
|
}
|
||||||
FreeFlyModeFlag = true; // Ra: automatycznie włączone latanie
|
FreeFlyModeFlag = true; // Ra: automatycznie włączone latanie
|
||||||
Camera.Type = TCameraType::tp_Free;
|
Camera.m_owner = nullptr;
|
||||||
DebugCamera = Camera;
|
DebugCamera = Camera;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,34 +395,42 @@ driver_mode::update_camera( double const Deltatime ) {
|
|||||||
nullptr );
|
nullptr );
|
||||||
|
|
||||||
if( false == Global.ControlPicking ) {
|
if( false == Global.ControlPicking ) {
|
||||||
|
|
||||||
if( m_input.mouse.button( GLFW_MOUSE_BUTTON_LEFT ) == GLFW_PRESS ) {
|
if( m_input.mouse.button( GLFW_MOUSE_BUTTON_LEFT ) == GLFW_PRESS ) {
|
||||||
Camera.Reset(); // likwidacja obrotów - patrzy horyzontalnie na południe
|
Camera.Reset(); // likwidacja obrotów - patrzy horyzontalnie na południe
|
||||||
if( controlled && LengthSquared3( controlled->GetPosition() - Camera.Pos ) < ( 1500 * 1500 ) ) {
|
if( Camera.m_owner == nullptr ) {
|
||||||
// gdy bliżej niż 1.5km
|
if( controlled && LengthSquared3( controlled->GetPosition() - Camera.Pos ) < ( 1500 * 1500 ) ) {
|
||||||
Camera.LookAt = controlled->GetPosition();
|
// gdy bliżej niż 1.5km
|
||||||
|
Camera.LookAt = controlled->GetPosition();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TDynamicObject *d = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global.pCamera.Pos, 300, false, false ) );
|
||||||
|
if( !d )
|
||||||
|
d = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global.pCamera.Pos, 1000, false, false ) ); // dalej szukanie, jesli bliżej nie ma
|
||||||
|
|
||||||
|
if( d && pDynamicNearest ) {
|
||||||
|
// jeśli jakiś jest znaleziony wcześniej
|
||||||
|
if( 100.0 * LengthSquared3( d->GetPosition() - Camera.Pos ) > LengthSquared3( pDynamicNearest->GetPosition() - Camera.Pos ) ) {
|
||||||
|
d = pDynamicNearest; // jeśli najbliższy nie jest 10 razy bliżej niż
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// poprzedni najbliższy, zostaje poprzedni
|
||||||
|
if( d )
|
||||||
|
pDynamicNearest = d; // zmiana na nowy, jeśli coś znaleziony niepusty
|
||||||
|
if( pDynamicNearest )
|
||||||
|
Camera.LookAt = pDynamicNearest->GetPosition();
|
||||||
|
}
|
||||||
|
Camera.RaLook(); // jednorazowe przestawienie kamery
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
TDynamicObject *d = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global.pCamera.Pos, 300, false, false ) );
|
if( false == FreeFlyModeFlag ) {
|
||||||
if( !d )
|
// reset cached view angle in the cab
|
||||||
d = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global.pCamera.Pos, 1000, false, false ) ); // dalej szukanie, jesli bliżej nie ma
|
simulation::Train->pMechViewAngle = { Camera.Angle.x, Camera.Angle.y };
|
||||||
|
|
||||||
if( d && pDynamicNearest ) {
|
|
||||||
// jeśli jakiś jest znaleziony wcześniej
|
|
||||||
if( 100.0 * LengthSquared3( d->GetPosition() - Camera.Pos ) > LengthSquared3( pDynamicNearest->GetPosition() - Camera.Pos ) ) {
|
|
||||||
d = pDynamicNearest; // jeśli najbliższy nie jest 10 razy bliżej niż
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// poprzedni najbliższy, zostaje poprzedni
|
|
||||||
if( d )
|
|
||||||
pDynamicNearest = d; // zmiana na nowy, jeśli coś znaleziony niepusty
|
|
||||||
if( pDynamicNearest )
|
|
||||||
Camera.LookAt = pDynamicNearest->GetPosition();
|
|
||||||
}
|
}
|
||||||
if( FreeFlyModeFlag )
|
|
||||||
Camera.RaLook(); // jednorazowe przestawienie kamery
|
|
||||||
}
|
}
|
||||||
else if( m_input.mouse.button( GLFW_MOUSE_BUTTON_RIGHT ) == GLFW_PRESS ) {
|
else if( m_input.mouse.button( GLFW_MOUSE_BUTTON_RIGHT ) == GLFW_PRESS ) {
|
||||||
FollowView( false ); // bez wyciszania dźwięków
|
CabView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,28 +444,49 @@ driver_mode::update_camera( double const Deltatime ) {
|
|||||||
Global.ZoomFactor = std::max( 1.0f, Global.ZoomFactor - 15.0f * static_cast<float>( Deltatime ) );
|
Global.ZoomFactor = std::max( 1.0f, Global.ZoomFactor - 15.0f * static_cast<float>( Deltatime ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( DebugCameraFlag ) { DebugCamera.Update(); }
|
// uwzględnienie ruchu wywołanego klawiszami
|
||||||
else { Camera.Update(); } // uwzględnienie ruchu wywołanego klawiszami
|
if( false == DebugCameraFlag ) {
|
||||||
|
// regular camera
|
||||||
if( ( false == FreeFlyModeFlag )
|
if( ( false == FreeFlyModeFlag )
|
||||||
&& ( false == Global.CabWindowOpen )
|
&& ( false == Global.CabWindowOpen ) ) {
|
||||||
&& ( simulation::Train != nullptr ) ) {
|
// if in cab potentially alter camera placement based on changes in train object
|
||||||
// cache cab camera view angles in case of view type switch
|
Camera.m_owneroffset = simulation::Train->pMechOffset;
|
||||||
simulation::Train->pMechViewAngle = { Camera.Pitch, Camera.Yaw };
|
Camera.Angle.x = simulation::Train->pMechViewAngle.x;
|
||||||
}
|
Camera.Angle.y = simulation::Train->pMechViewAngle.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
Camera.Update();
|
||||||
|
|
||||||
|
if( false == FreeFlyModeFlag ) {
|
||||||
|
// keep the camera within cab boundaries
|
||||||
|
Camera.m_owneroffset = simulation::Train->clamp_inside( Camera.m_owneroffset );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( false == FreeFlyModeFlag )
|
||||||
|
&& ( false == Global.CabWindowOpen ) ) {
|
||||||
|
// cache cab camera in case of view type switch
|
||||||
|
simulation::Train->pMechViewAngle = { Camera.Angle.x, Camera.Angle.y };
|
||||||
|
simulation::Train->pMechOffset = Camera.m_owneroffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// debug camera
|
||||||
|
DebugCamera.Update();
|
||||||
|
}
|
||||||
|
|
||||||
// reset window state, it'll be set again if applicable in a check below
|
// reset window state, it'll be set again if applicable in a check below
|
||||||
Global.CabWindowOpen = false;
|
Global.CabWindowOpen = false;
|
||||||
|
|
||||||
if( ( simulation::Train != nullptr )
|
if( ( simulation::Train != nullptr )
|
||||||
&& ( Camera.Type == TCameraType::tp_Follow )
|
&& ( Camera.m_owner != nullptr )
|
||||||
&& ( false == DebugCameraFlag ) ) {
|
&& ( false == DebugCameraFlag ) ) {
|
||||||
// jeśli jazda w kabinie, przeliczyć trzeba parametry kamery
|
// jeśli jazda w kabinie, przeliczyć trzeba parametry kamery
|
||||||
/*
|
/*
|
||||||
auto tempangle = controlled->VectorFront() * ( controlled->MoverParameters->ActiveCab == -1 ? -1 : 1 );
|
auto tempangle = controlled->VectorFront() * ( controlled->MoverParameters->ActiveCab == -1 ? -1 : 1 );
|
||||||
double modelrotate = atan2( -tempangle.x, tempangle.z );
|
double modelrotate = atan2( -tempangle.x, tempangle.z );
|
||||||
*/
|
*/
|
||||||
if( ( true == Global.ctrlState )
|
if( ( false == FreeFlyModeFlag )
|
||||||
|
&& ( true == Global.ctrlState )
|
||||||
&& ( ( m_input.keyboard.key( GLFW_KEY_LEFT ) != GLFW_RELEASE )
|
&& ( ( m_input.keyboard.key( GLFW_KEY_LEFT ) != GLFW_RELEASE )
|
||||||
|| ( m_input.keyboard.key( GLFW_KEY_RIGHT ) != GLFW_RELEASE ) ) ) {
|
|| ( m_input.keyboard.key( GLFW_KEY_RIGHT ) != GLFW_RELEASE ) ) ) {
|
||||||
// jeśli lusterko lewe albo prawe (bez rzucania na razie)
|
// jeśli lusterko lewe albo prawe (bez rzucania na razie)
|
||||||
@@ -469,9 +495,11 @@ driver_mode::update_camera( double const Deltatime ) {
|
|||||||
auto const lr { m_input.keyboard.key( GLFW_KEY_LEFT ) != GLFW_RELEASE };
|
auto const lr { m_input.keyboard.key( GLFW_KEY_LEFT ) != GLFW_RELEASE };
|
||||||
// Camera.Yaw powinno być wyzerowane, aby po powrocie patrzeć do przodu
|
// Camera.Yaw powinno być wyzerowane, aby po powrocie patrzeć do przodu
|
||||||
Camera.Pos = controlled->GetPosition() + simulation::Train->MirrorPosition( lr ); // pozycja lusterka
|
Camera.Pos = controlled->GetPosition() + simulation::Train->MirrorPosition( lr ); // pozycja lusterka
|
||||||
Camera.Yaw = 0; // odchylenie na bok od Camera.LookAt
|
Camera.Angle.y = 0; // odchylenie na bok od Camera.LookAt
|
||||||
if( simulation::Train->Occupied()->ActiveCab == 0 )
|
if( simulation::Train->Occupied()->ActiveCab == 0 ) {
|
||||||
Camera.LookAt = Camera.Pos - simulation::Train->GetDirection(); // gdy w korytarzu
|
// gdy w korytarzu
|
||||||
|
Camera.LookAt = Camera.Pos - simulation::Train->GetDirection();
|
||||||
|
}
|
||||||
else if( Global.shiftState ) {
|
else if( Global.shiftState ) {
|
||||||
// patrzenie w bok przez szybę
|
// patrzenie w bok przez szybę
|
||||||
Camera.LookAt = Camera.Pos - ( lr ? -1 : 1 ) * controlled->VectorLeft() * simulation::Train->Occupied()->ActiveCab;
|
Camera.LookAt = Camera.Pos - ( lr ? -1 : 1 ) * controlled->VectorLeft() * simulation::Train->Occupied()->ActiveCab;
|
||||||
@@ -480,25 +508,47 @@ driver_mode::update_camera( double const Deltatime ) {
|
|||||||
// ale bez odbicia
|
// ale bez odbicia
|
||||||
Camera.LookAt = Camera.Pos - simulation::Train->GetDirection() * simulation::Train->Occupied()->ActiveCab; //-1 albo 1
|
Camera.LookAt = Camera.Pos - simulation::Train->GetDirection() * simulation::Train->Occupied()->ActiveCab; //-1 albo 1
|
||||||
}
|
}
|
||||||
Camera.Roll = std::atan( simulation::Train->pMechShake.x * simulation::Train->fMechRoll ); // hustanie kamery na boki
|
auto const shakeangles { simulation::Train->Dynamic()->shake_angles() };
|
||||||
Camera.Pitch = 0.5 * std::atan( simulation::Train->vMechVelocity.z * simulation::Train->fMechPitch ); // hustanie kamery przod tyl
|
Camera.Angle.x = 0.5 * shakeangles.second; // hustanie kamery przod tyl
|
||||||
|
Camera.Angle.z = shakeangles.first; // hustanie kamery na boki
|
||||||
|
/*
|
||||||
|
Camera.Roll = std::atan( simulation::Train->pMechShake.x * simulation::Train->BaseShake.angle_scale.x ); // hustanie kamery na boki
|
||||||
|
Camera.Pitch = 0.5 * std::atan( simulation::Train->vMechVelocity.z * simulation::Train->BaseShake.angle_scale.z ); // hustanie kamery przod tyl
|
||||||
|
*/
|
||||||
Camera.vUp = controlled->VectorUp();
|
Camera.vUp = controlled->VectorUp();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// patrzenie standardowe
|
// patrzenie standardowe
|
||||||
// potentially restore view angle after returning from external view
|
if( false == FreeFlyModeFlag ) {
|
||||||
// TODO: mirror view toggle as separate method
|
// potentially restore view angle after returning from external view
|
||||||
Camera.Pitch = simulation::Train->pMechViewAngle.x;
|
// TODO: mirror view toggle as separate method
|
||||||
Camera.Yaw = simulation::Train->pMechViewAngle.y;
|
Camera.Angle.x = simulation::Train->pMechViewAngle.x;
|
||||||
|
Camera.Angle.y = simulation::Train->pMechViewAngle.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const shakescale { FreeFlyModeFlag ? 5.0 : 1.0 };
|
||||||
|
auto shakencamerapos {
|
||||||
|
Camera.m_owneroffset
|
||||||
|
+ shakescale * Math3D::vector3(
|
||||||
|
1.5 * Camera.m_owner->ShakeState.offset.x,
|
||||||
|
2.0 * Camera.m_owner->ShakeState.offset.y,
|
||||||
|
1.5 * Camera.m_owner->ShakeState.offset.z ) };
|
||||||
|
|
||||||
|
Camera.Pos = (
|
||||||
|
Camera.m_owner->GetWorldPosition (
|
||||||
|
FreeFlyModeFlag ?
|
||||||
|
shakencamerapos : // TODO: vehicle collision box for the external vehicle camera
|
||||||
|
simulation::Train->clamp_inside( shakencamerapos ) ) );
|
||||||
|
|
||||||
Camera.Pos = simulation::Train->GetWorldMechPosition(); // Train.GetPosition1();
|
|
||||||
if( !Global.iPause ) {
|
if( !Global.iPause ) {
|
||||||
// podczas pauzy nie przeliczać kątów przypadkowymi wartościami
|
// podczas pauzy nie przeliczać kątów przypadkowymi wartościami
|
||||||
// hustanie kamery na boki
|
auto const shakeangles { Camera.m_owner->shake_angles() };
|
||||||
Camera.Roll = atan( simulation::Train->vMechVelocity.x * simulation::Train->fMechRoll );
|
Camera.Angle.x -= 0.5 * shakeangles.second; // hustanie kamery przod tyl
|
||||||
// hustanie kamery przod tyl
|
Camera.Angle.z = shakeangles.first; // hustanie kamery na boki
|
||||||
// Ra: tu jest uciekanie kamery w górę!!!
|
/*
|
||||||
Camera.Pitch -= 0.5 * atan( simulation::Train->vMechVelocity.z * simulation::Train->fMechPitch );
|
Camera.Roll = std::atan( simulation::Train->vMechVelocity.x * simulation::Train->BaseShake.angle_scale.x ); // hustanie kamery na boki
|
||||||
|
Camera.Pitch -= 0.5 * atan( simulation::Train->vMechVelocity.z * simulation::Train->BaseShake.angle_scale.z ); // hustanie kamery przod tyl
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
// ABu011104: rzucanie pudlem
|
// ABu011104: rzucanie pudlem
|
||||||
@@ -513,10 +563,19 @@ driver_mode::update_camera( double const Deltatime ) {
|
|||||||
Controlled->ABuSetModelShake( temp );
|
Controlled->ABuSetModelShake( temp );
|
||||||
// ABu: koniec rzucania
|
// ABu: koniec rzucania
|
||||||
*/
|
*/
|
||||||
if( simulation::Train->Occupied()->ActiveCab == 0 )
|
if( simulation::Train->Occupied()->ActiveCab == 0 ) {
|
||||||
Camera.LookAt = simulation::Train->GetWorldMechPosition() + simulation::Train->GetDirection() * 5.0; // gdy w korytarzu
|
// gdy w korytarzu
|
||||||
else // patrzenie w kierunku osi pojazdu, z uwzględnieniem kabiny
|
Camera.LookAt =
|
||||||
Camera.LookAt = simulation::Train->GetWorldMechPosition() + simulation::Train->GetDirection() * 5.0 * simulation::Train->Occupied()->ActiveCab; //-1 albo 1
|
Camera.m_owner->GetWorldPosition( Camera.m_owneroffset )
|
||||||
|
+ simulation::Train->GetDirection() * 5.0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// patrzenie w kierunku osi pojazdu, z uwzględnieniem kabiny
|
||||||
|
Camera.LookAt =
|
||||||
|
Camera.m_owner->GetWorldPosition( Camera.m_owneroffset )
|
||||||
|
+ simulation::Train->GetDirection() * 5.0
|
||||||
|
* simulation::Train->Occupied()->ActiveCab; //-1 albo 1
|
||||||
|
}
|
||||||
Camera.vUp = simulation::Train->GetUp();
|
Camera.vUp = simulation::Train->GetUp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -591,9 +650,7 @@ driver_mode::OnKeyDown(int cKey) {
|
|||||||
&& ( Global.FreeCameraInit[ i ].z == 0.0 ) ) {
|
&& ( Global.FreeCameraInit[ i ].z == 0.0 ) ) {
|
||||||
// jeśli kamera jest w punkcie zerowym, zapamiętanie współrzędnych i kątów
|
// jeśli kamera jest w punkcie zerowym, zapamiętanie współrzędnych i kątów
|
||||||
Global.FreeCameraInit[ i ] = Camera.Pos;
|
Global.FreeCameraInit[ i ] = Camera.Pos;
|
||||||
Global.FreeCameraInitAngle[ i ].x = Camera.Pitch;
|
Global.FreeCameraInitAngle[ i ] = Camera.Angle;
|
||||||
Global.FreeCameraInitAngle[ i ].y = Camera.Yaw;
|
|
||||||
Global.FreeCameraInitAngle[ i ].z = Camera.Roll;
|
|
||||||
// logowanie, żeby można było do scenerii przepisać
|
// logowanie, żeby można było do scenerii przepisać
|
||||||
WriteLog(
|
WriteLog(
|
||||||
"camera " + std::to_string( Global.FreeCameraInit[ i ].x ) + " "
|
"camera " + std::to_string( Global.FreeCameraInit[ i ].x ) + " "
|
||||||
@@ -607,7 +664,7 @@ driver_mode::OnKeyDown(int cKey) {
|
|||||||
else // również przeskakiwanie
|
else // również przeskakiwanie
|
||||||
{ // Ra: to z tą kamerą (Camera.Pos i Global.pCameraPosition) jest trochę bez sensu
|
{ // Ra: to z tą kamerą (Camera.Pos i Global.pCameraPosition) jest trochę bez sensu
|
||||||
Global.pCamera.Pos = Global.FreeCameraInit[ i ]; // nowa pozycja dla generowania obiektów
|
Global.pCamera.Pos = Global.FreeCameraInit[ i ]; // nowa pozycja dla generowania obiektów
|
||||||
Camera.Init( Global.FreeCameraInit[ i ], Global.FreeCameraInitAngle[ i ], TCameraType::tp_Free ); // przestawienie
|
Camera.Init( Global.FreeCameraInit[ i ], Global.FreeCameraInitAngle[ i ], nullptr ); // przestawienie
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -633,8 +690,9 @@ driver_mode::OnKeyDown(int cKey) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case GLFW_KEY_F4: {
|
case GLFW_KEY_F4: {
|
||||||
|
|
||||||
InOutKey( !Global.shiftState ); // distant view with Shift, short distance step out otherwise
|
if( Global.shiftState ) { ExternalView(); } // with Shift, cycle through external views
|
||||||
|
else { InOutKey(); } // without, step out of the cab or return to it
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GLFW_KEY_F5: {
|
case GLFW_KEY_F5: {
|
||||||
@@ -823,52 +881,150 @@ driver_mode::DistantView( bool const Near ) {
|
|||||||
+ Math3D::vector3( -10.0 * left.x, 1.6, -10.0 * left.z );
|
+ Math3D::vector3( -10.0 * left.x, 1.6, -10.0 * left.z );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Camera.m_owner = nullptr;
|
||||||
Camera.LookAt = vehicle->GetPosition();
|
Camera.LookAt = vehicle->GetPosition();
|
||||||
Camera.RaLook(); // jednorazowe przestawienie kamery
|
Camera.RaLook(); // jednorazowe przestawienie kamery
|
||||||
}
|
}
|
||||||
|
|
||||||
// ustawienie śledzenia pojazdu
|
|
||||||
void
|
void
|
||||||
driver_mode::FollowView(bool wycisz) {
|
driver_mode::ExternalView() {
|
||||||
|
|
||||||
Camera.Reset(); // likwidacja obrotów - patrzy horyzontalnie na południe
|
|
||||||
|
|
||||||
auto *train { simulation::Train };
|
auto *train { simulation::Train };
|
||||||
|
if( train == nullptr ) { return; }
|
||||||
|
|
||||||
if (train != nullptr ) // jest pojazd do prowadzenia?
|
auto *vehicle { train->Dynamic() };
|
||||||
{
|
|
||||||
if (FreeFlyModeFlag)
|
|
||||||
{ // jeżeli poza kabiną, przestawiamy w jej okolicę - OK
|
|
||||||
// wyłączenie trzęsienia na siłę?
|
|
||||||
train->Dynamic()->ABuSetModelShake( {} );
|
|
||||||
|
|
||||||
DistantView(); // przestawienie kamery
|
// disable detailed cab in external view modes
|
||||||
|
vehicle->bDisplayCab = false;
|
||||||
|
|
||||||
|
if( true == m_externalview ) {
|
||||||
|
// we're already in some external view mode, so select next one on the list
|
||||||
|
m_externalviewmode = clamp_circular( ++m_externalviewmode, static_cast<int>( view::count_ ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeFlyModeFlag = true;
|
||||||
|
m_externalview = true;
|
||||||
|
|
||||||
|
Camera.Reset();
|
||||||
|
// configure camera placement for the selected view mode
|
||||||
|
switch( m_externalviewmode ) {
|
||||||
|
case view::consistfront: {
|
||||||
|
// bind camera with the vehicle
|
||||||
|
auto *owner { vehicle->Mechanik->Vehicle( side::front ) };
|
||||||
|
|
||||||
|
Camera.m_owner = owner;
|
||||||
|
|
||||||
|
auto const offsetflip {
|
||||||
|
( vehicle->MoverParameters->ActiveCab == 0 ? 1 : vehicle->MoverParameters->ActiveCab )
|
||||||
|
* ( vehicle->MoverParameters->ActiveDir == 0 ? 1 : vehicle->MoverParameters->ActiveDir ) };
|
||||||
|
|
||||||
|
Camera.m_owneroffset = {
|
||||||
|
1.5 * owner->MoverParameters->Dim.W * offsetflip,
|
||||||
|
std::max( 5.0, 1.25 * owner->MoverParameters->Dim.H ),
|
||||||
|
- 0.4 * owner->MoverParameters->Dim.L * offsetflip };
|
||||||
|
|
||||||
|
Camera.Angle.y = glm::radians( ( vehicle->MoverParameters->ActiveDir < 0 ? 180.0 : 0.0 ) );
|
||||||
|
|
||||||
|
auto const shakeangles { owner->shake_angles() };
|
||||||
|
Camera.Angle.x -= 0.5 * shakeangles.second; // hustanie kamery przod tyl
|
||||||
|
Camera.Angle.z = shakeangles.first; // hustanie kamery na boki
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else {
|
case view::consistrear: {
|
||||||
Camera.Pos = train->pMechPosition;
|
// bind camera with the vehicle
|
||||||
// potentially restore cached camera angles
|
auto *owner { vehicle->Mechanik->Vehicle( side::rear ) };
|
||||||
Camera.Pitch = train->pMechViewAngle.x;
|
|
||||||
Camera.Yaw = train->pMechViewAngle.y;
|
|
||||||
|
|
||||||
Camera.Roll = std::atan(train->pMechShake.x * train->fMechRoll); // hustanie kamery na boki
|
Camera.m_owner = owner;
|
||||||
Camera.Pitch -= 0.5 * std::atan(train->vMechVelocity.z * train->fMechPitch); // hustanie kamery przod tyl
|
|
||||||
|
|
||||||
if( train->Occupied()->ActiveCab == 0 ) {
|
auto const offsetflip {
|
||||||
Camera.LookAt =
|
( vehicle->MoverParameters->ActiveCab == 0 ? 1 : vehicle->MoverParameters->ActiveCab )
|
||||||
train->pMechPosition
|
* ( vehicle->MoverParameters->ActiveDir == 0 ? 1 : vehicle->MoverParameters->ActiveDir )
|
||||||
+ train->GetDirection() * 5.0;
|
* -1 };
|
||||||
}
|
|
||||||
else {
|
Camera.m_owneroffset = {
|
||||||
// patrz w strone wlasciwej kabiny
|
1.5 * owner->MoverParameters->Dim.W * offsetflip,
|
||||||
Camera.LookAt =
|
std::max( 5.0, 1.25 * owner->MoverParameters->Dim.H ),
|
||||||
train->pMechPosition
|
0.2 * owner->MoverParameters->Dim.L * offsetflip };
|
||||||
+ train->GetDirection() * 5.0 * train->Occupied()->ActiveCab;
|
|
||||||
}
|
Camera.Angle.y = glm::radians( ( vehicle->MoverParameters->ActiveDir < 0 ? 0.0 : 180.0 ) );
|
||||||
train->pMechOffset = train->pMechSittingPosition;
|
|
||||||
|
auto const shakeangles { owner->shake_angles() };
|
||||||
|
Camera.Angle.x -= 0.5 * shakeangles.second; // hustanie kamery przod tyl
|
||||||
|
Camera.Angle.z = shakeangles.first; // hustanie kamery na boki
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case view::bogie: {
|
||||||
|
auto *owner { vehicle->Mechanik->Vehicle( side::front ) };
|
||||||
|
|
||||||
|
Camera.m_owner = owner;
|
||||||
|
|
||||||
|
auto const offsetflip {
|
||||||
|
( vehicle->MoverParameters->ActiveCab == 0 ? 1 : vehicle->MoverParameters->ActiveCab )
|
||||||
|
* ( vehicle->MoverParameters->ActiveDir == 0 ? 1 : vehicle->MoverParameters->ActiveDir ) };
|
||||||
|
|
||||||
|
Camera.m_owneroffset = {
|
||||||
|
- 0.65 * owner->MoverParameters->Dim.W * offsetflip,
|
||||||
|
0.90,
|
||||||
|
0.15 * owner->MoverParameters->Dim.L * offsetflip };
|
||||||
|
|
||||||
|
Camera.Angle.y = glm::radians( ( vehicle->MoverParameters->ActiveDir < 0 ? 180.0 : 0.0 ) );
|
||||||
|
|
||||||
|
auto const shakeangles { owner->shake_angles() };
|
||||||
|
Camera.Angle.x -= 0.5 * shakeangles.second; // hustanie kamery przod tyl
|
||||||
|
Camera.Angle.z = shakeangles.first; // hustanie kamery na boki
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case view::driveby: {
|
||||||
|
DistantView( false );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
DistantView();
|
|
||||||
|
// ustawienie śledzenia pojazdu
|
||||||
|
void
|
||||||
|
driver_mode::CabView() {
|
||||||
|
|
||||||
|
// TODO: configure owner and camera placement depending on the view mode
|
||||||
|
if( true == FreeFlyModeFlag ) { return; }
|
||||||
|
|
||||||
|
auto *train { simulation::Train };
|
||||||
|
if( train == nullptr ) { return; }
|
||||||
|
|
||||||
|
m_externalview = false;
|
||||||
|
|
||||||
|
// likwidacja obrotów - patrzy horyzontalnie na południe
|
||||||
|
Camera.Reset();
|
||||||
|
|
||||||
|
// bind camera with the vehicle
|
||||||
|
Camera.m_owner = train->Dynamic();
|
||||||
|
// potentially restore cached camera setup
|
||||||
|
Camera.m_owneroffset = train->pMechSittingPosition;
|
||||||
|
Camera.Angle.x = train->pMechViewAngle.x;
|
||||||
|
Camera.Angle.y = train->pMechViewAngle.y;
|
||||||
|
|
||||||
|
auto const shakeangles { Camera.m_owner->shake_angles() };
|
||||||
|
Camera.Angle.x -= 0.5 * shakeangles.second; // hustanie kamery przod tyl
|
||||||
|
Camera.Angle.z = shakeangles.first; // hustanie kamery na boki
|
||||||
|
|
||||||
|
if( train->Occupied()->ActiveCab == 0 ) {
|
||||||
|
Camera.LookAt =
|
||||||
|
Camera.m_owner->GetWorldPosition( Camera.m_owneroffset )
|
||||||
|
+ Camera.m_owner->VectorFront() * 5.0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// patrz w strone wlasciwej kabiny
|
||||||
|
Camera.LookAt =
|
||||||
|
Camera.m_owner->GetWorldPosition( Camera.m_owneroffset )
|
||||||
|
+ Camera.m_owner->VectorFront() * 5.0
|
||||||
|
* Camera.m_owner->MoverParameters->ActiveCab;
|
||||||
|
}
|
||||||
|
train->pMechOffset = Camera.m_owneroffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -925,43 +1081,41 @@ driver_mode::ChangeDynamic() {
|
|||||||
if( false == FreeFlyModeFlag ) {
|
if( false == FreeFlyModeFlag ) {
|
||||||
vehicle->bDisplayCab = true;
|
vehicle->bDisplayCab = true;
|
||||||
vehicle->ABuSetModelShake( {} ); // zerowanie przesunięcia przed powrotem?
|
vehicle->ABuSetModelShake( {} ); // zerowanie przesunięcia przed powrotem?
|
||||||
train->MechStop();
|
CabView(); // na pozycję mecha
|
||||||
FollowView(); // na pozycję mecha
|
|
||||||
}
|
}
|
||||||
Global.changeDynObj = nullptr;
|
Global.changeDynObj = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
driver_mode::InOutKey( bool const Near )
|
driver_mode::InOutKey()
|
||||||
{ // przełączenie widoku z kabiny na zewnętrzny i odwrotnie
|
{ // przełączenie widoku z kabiny na zewnętrzny i odwrotnie
|
||||||
FreeFlyModeFlag = !FreeFlyModeFlag; // zmiana widoku
|
FreeFlyModeFlag = !FreeFlyModeFlag; // zmiana widoku
|
||||||
|
|
||||||
auto *train { simulation::Train };
|
auto *train { simulation::Train };
|
||||||
|
|
||||||
|
if( train == nullptr ) {
|
||||||
|
FreeFlyModeFlag = true; // nadal poza kabiną
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *vehicle { train->Dynamic() };
|
||||||
|
|
||||||
if (FreeFlyModeFlag) {
|
if (FreeFlyModeFlag) {
|
||||||
// jeżeli poza kabiną, przestawiamy w jej okolicę - OK
|
// jeżeli poza kabiną, przestawiamy w jej okolicę - OK
|
||||||
if (train) {
|
// cache current cab position so there's no need to set it all over again after each out-in switch
|
||||||
// cache current cab position so there's no need to set it all over again after each out-in switch
|
train->pMechSittingPosition = train->pMechOffset;
|
||||||
train->pMechSittingPosition = train->pMechOffset;
|
|
||||||
|
vehicle->bDisplayCab = false;
|
||||||
|
DistantView( true );
|
||||||
|
|
||||||
train->Dynamic()->bDisplayCab = false;
|
|
||||||
DistantView( Near );
|
|
||||||
}
|
|
||||||
DebugCamera = Camera;
|
DebugCamera = Camera;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{ // jazda w kabinie
|
// jazda w kabinie
|
||||||
if (train)
|
// zerowanie przesunięcia przed powrotem?
|
||||||
{
|
vehicle->ABuSetModelShake( { 0, 0, 0 } );
|
||||||
train->Dynamic()->bDisplayCab = true;
|
vehicle->bDisplayCab = true;
|
||||||
// zerowanie przesunięcia przed powrotem?
|
CabView(); // na pozycję mecha
|
||||||
train->Dynamic()->ABuSetModelShake( { 0, 0, 0 } );
|
|
||||||
train->MechStop();
|
|
||||||
FollowView(); // na pozycję mecha
|
|
||||||
train->UpdateMechPosition( m_secondaryupdaterate );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
FreeFlyModeFlag = true; // nadal poza kabiną
|
|
||||||
}
|
}
|
||||||
// update window title to reflect the situation
|
// update window title to reflect the situation
|
||||||
Application.set_title( Global.AppName + " (" + ( train != nullptr ? train->Occupied()->Name : "" ) + " @ " + Global.SceneryFile + ")" );
|
Application.set_title( Global.AppName + " (" + ( train != nullptr ? train->Occupied()->Name : "" ) + " @ " + Global.SceneryFile + ")" );
|
||||||
|
|||||||
15
drivermode.h
15
drivermode.h
@@ -52,6 +52,14 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// types
|
// types
|
||||||
|
enum view {
|
||||||
|
consistfront,
|
||||||
|
consistrear,
|
||||||
|
bogie,
|
||||||
|
driveby,
|
||||||
|
count_
|
||||||
|
};
|
||||||
|
|
||||||
struct drivermode_input {
|
struct drivermode_input {
|
||||||
|
|
||||||
gamepad_input gamepad;
|
gamepad_input gamepad;
|
||||||
@@ -70,8 +78,9 @@ private:
|
|||||||
// handles vehicle change flag
|
// handles vehicle change flag
|
||||||
void OnKeyDown( int cKey );
|
void OnKeyDown( int cKey );
|
||||||
void ChangeDynamic();
|
void ChangeDynamic();
|
||||||
void InOutKey( bool const Near = true );
|
void InOutKey();
|
||||||
void FollowView( bool wycisz = true );
|
void CabView();
|
||||||
|
void ExternalView();
|
||||||
void DistantView( bool const Near = false );
|
void DistantView( bool const Near = false );
|
||||||
void set_picking( bool const Picking );
|
void set_picking( bool const Picking );
|
||||||
|
|
||||||
@@ -80,6 +89,8 @@ private:
|
|||||||
std::array<basic_event *, 10> KeyEvents { nullptr }; // eventy wyzwalane z klawiaury
|
std::array<basic_event *, 10> KeyEvents { nullptr }; // eventy wyzwalane z klawiaury
|
||||||
TCamera Camera;
|
TCamera Camera;
|
||||||
TCamera DebugCamera;
|
TCamera DebugCamera;
|
||||||
|
int m_externalviewmode { view::consistfront }; // selected external view mode
|
||||||
|
bool m_externalview { false };
|
||||||
TDynamicObject *pDynamicNearest { nullptr }; // vehicle nearest to the active camera. TODO: move to camera
|
TDynamicObject *pDynamicNearest { nullptr }; // vehicle nearest to the active camera. TODO: move to camera
|
||||||
double fTime50Hz { 0.0 }; // bufor czasu dla komunikacji z PoKeys
|
double fTime50Hz { 0.0 }; // bufor czasu dla komunikacji z PoKeys
|
||||||
double const m_primaryupdaterate { 1.0 / 100.0 };
|
double const m_primaryupdaterate { 1.0 / 100.0 };
|
||||||
|
|||||||
@@ -852,10 +852,10 @@ debug_panel::update_section_camera( std::vector<text_line> &Output ) {
|
|||||||
|
|
||||||
textline =
|
textline =
|
||||||
"Azimuth: "
|
"Azimuth: "
|
||||||
+ to_string( 180.0 - glm::degrees( camera.Yaw ), 0 ) // ma być azymut, czyli 0 na północy i rośnie na wschód
|
+ to_string( 180.0 - glm::degrees( camera.Angle.y ), 0 ) // ma być azymut, czyli 0 na północy i rośnie na wschód
|
||||||
+ " "
|
+ " "
|
||||||
+ std::string( "S SEE NEN NWW SW" )
|
+ std::string( "S SEE NEN NWW SW" )
|
||||||
.substr( 0 + 2 * floor( fmod( 8 + ( camera.Yaw + 0.5 * M_PI_4 ) / M_PI_4, 8 ) ), 2 );
|
.substr( 0 + 2 * floor( fmod( 8 + ( camera.Angle.y + 0.5 * M_PI_4 ) / M_PI_4, 8 ) ), 2 );
|
||||||
|
|
||||||
Output.emplace_back( textline, Global.UITextColor );
|
Output.emplace_back( textline, Global.UITextColor );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ editor_mode::editor_mode() {
|
|||||||
bool
|
bool
|
||||||
editor_mode::init() {
|
editor_mode::init() {
|
||||||
|
|
||||||
Camera.Init( { 0, 15, 0 }, { glm::radians( -30.0 ), glm::radians( 180.0 ), 0 }, TCameraType::tp_Free );
|
Camera.Init( { 0, 15, 0 }, { glm::radians( -30.0 ), glm::radians( 180.0 ), 0 }, nullptr );
|
||||||
|
|
||||||
return m_input.init();
|
return m_input.init();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user