mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
build 180527. smoother camera rotation, semi-persistent cab camera angle between view swaps, configurable default cab camera view angle, diesel engine power calculation fix, minor refactoring and fixes for content files lookups and loading
This commit is contained in:
47
Camera.cpp
47
Camera.cpp
@@ -18,8 +18,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void TCamera::Init( Math3D::vector3 NPos, Math3D::vector3 NAngle)
|
||||
{
|
||||
void TCamera::Init( Math3D::vector3 NPos, Math3D::vector3 NAngle) {
|
||||
|
||||
vUp = Math3D::vector3(0, 1, 0);
|
||||
Velocity = Math3D::vector3(0, 0, 0);
|
||||
@@ -31,8 +30,15 @@ void TCamera::Init( Math3D::vector3 NPos, Math3D::vector3 NAngle)
|
||||
Type = (Global.bFreeFly ? tp_Free : tp_Follow);
|
||||
};
|
||||
|
||||
void TCamera::OnCursorMove(double x, double y) {
|
||||
void TCamera::Reset() {
|
||||
|
||||
Pitch = Yaw = Roll = 0;
|
||||
m_rotationoffsets = {};
|
||||
};
|
||||
|
||||
|
||||
void TCamera::OnCursorMove(double x, double y) {
|
||||
/*
|
||||
Yaw -= x;
|
||||
while( Yaw > M_PI ) {
|
||||
Yaw -= 2 * M_PI;
|
||||
@@ -45,6 +51,8 @@ void TCamera::OnCursorMove(double x, double y) {
|
||||
// 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 };
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -151,8 +159,9 @@ void TCamera::Update()
|
||||
OnCommand( command );
|
||||
}
|
||||
|
||||
auto const deltatime = Timer::GetDeltaRenderTime(); // czas bez pauzy
|
||||
auto const deltatime { Timer::GetDeltaRenderTime() }; // czas bez pauzy
|
||||
|
||||
// update position
|
||||
if( ( Type == tp_Free )
|
||||
|| ( false == Global.ctrlState )
|
||||
|| ( true == DebugCameraFlag ) ) {
|
||||
@@ -170,6 +179,24 @@ void TCamera::Update()
|
||||
Vec.RotateY( Yaw );
|
||||
Pos += Vec * 5.0 * deltatime;
|
||||
}
|
||||
// update rotation
|
||||
auto const rotationfactor { std::min( 1.0, 20 * deltatime ) };
|
||||
|
||||
Yaw -= rotationfactor * m_rotationoffsets.y;
|
||||
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 == 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() {
|
||||
@@ -200,11 +227,15 @@ bool TCamera::SetMatrix( glm::dmat4 &Matrix ) {
|
||||
void TCamera::RaLook()
|
||||
{ // zmiana kierunku patrzenia - przelicza Yaw
|
||||
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))
|
||||
Yaw = atan2(-where.x, -where.z); // kąt horyzontalny
|
||||
if( ( where.x != 0.0 ) || ( where.z != 0.0 ) ) {
|
||||
Yaw = atan2( -where.x, -where.z ); // kąt horyzontalny
|
||||
m_rotationoffsets.y = 0.0;
|
||||
}
|
||||
double l = Math3D::Length3(where);
|
||||
if (l > 0.0)
|
||||
Pitch = asin(where.y / l); // kąt w pionie
|
||||
if( l > 0.0 ) {
|
||||
Pitch = asin( where.y / l ); // kąt w pionie
|
||||
m_rotationoffsets.x = 0.0;
|
||||
}
|
||||
};
|
||||
|
||||
void TCamera::Stop()
|
||||
|
||||
12
Camera.h
12
Camera.h
@@ -22,14 +22,9 @@ enum TCameraType
|
||||
|
||||
class TCamera {
|
||||
|
||||
private:
|
||||
glm::dvec3 m_moverate;
|
||||
|
||||
public: // McZapkie: potrzebuje do kiwania na boki
|
||||
void Init( Math3D::vector3 NPos, Math3D::vector3 NAngle);
|
||||
inline
|
||||
void Reset() {
|
||||
Pitch = Yaw = Roll = 0; };
|
||||
void Reset();
|
||||
void OnCursorMove(double const x, double const y);
|
||||
bool OnCommand( command_data const &Command );
|
||||
void Update();
|
||||
@@ -46,4 +41,9 @@ class TCamera {
|
||||
Math3D::vector3 LookAt; // współrzędne punktu, na który ma patrzeć
|
||||
Math3D::vector3 vUp;
|
||||
Math3D::vector3 Velocity;
|
||||
|
||||
private:
|
||||
glm::dvec3 m_moverate;
|
||||
glm::dvec3 m_rotationoffsets; // requested changes to pitch, yaw and roll
|
||||
|
||||
};
|
||||
|
||||
19
Driver.cpp
19
Driver.cpp
@@ -3222,17 +3222,24 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
|
||||
iStationStart = TrainParams->StationIndex;
|
||||
asNextStop = TrainParams->NextStop();
|
||||
iDrivigFlags |= movePrimary; // skoro dostał rozkład, to jest teraz głównym
|
||||
NewCommand = Global.asCurrentSceneryPath + NewCommand + ".wav"; // na razie jeden
|
||||
if (FileExists(NewCommand)) {
|
||||
NewCommand = Global.asCurrentSceneryPath + NewCommand;
|
||||
auto lookup =
|
||||
FileExists(
|
||||
{ NewCommand },
|
||||
{ ".ogg", ".flac", ".wav" } );
|
||||
if( false == lookup.first.empty() ) {
|
||||
// wczytanie dźwięku odjazdu podawanego bezpośrenido
|
||||
tsGuardSignal = sound_source( sound_placement::external, 75.f ).deserialize( NewCommand, sound_type::single );
|
||||
tsGuardSignal = sound_source( sound_placement::external, 75.f ).deserialize( lookup.first + lookup.second, sound_type::single );
|
||||
iGuardRadio = 0; // nie przez radio
|
||||
}
|
||||
else {
|
||||
NewCommand = NewCommand.insert(NewCommand.rfind('.'),"radio"); // wstawienie przed kropkč
|
||||
if (FileExists(NewCommand)) {
|
||||
auto lookup =
|
||||
FileExists(
|
||||
{ NewCommand + "radio" },
|
||||
{ ".ogg", ".flac", ".wav" } );
|
||||
if( false == lookup.first.empty() ) {
|
||||
// wczytanie dźwięku odjazdu w wersji radiowej (słychać tylko w kabinie)
|
||||
tsGuardSignal = sound_source( sound_placement::internal, 2 * EU07_SOUND_CABCONTROLSCUTOFFRANGE ).deserialize( NewCommand, sound_type::single );
|
||||
tsGuardSignal = sound_source( sound_placement::internal, 2 * EU07_SOUND_CABCONTROLSCUTOFFRANGE ).deserialize( lookup.first + lookup.second, sound_type::single );
|
||||
iGuardRadio = iRadioChannel;
|
||||
}
|
||||
}
|
||||
|
||||
46
DynObj.cpp
46
DynObj.cpp
@@ -50,6 +50,18 @@ GetSubmodelFromName( TModel3d * const Model, std::string const Name ) {
|
||||
nullptr );
|
||||
}
|
||||
|
||||
// Ra 2015-01: sprawdzenie dostępności tekstury o podanej nazwie
|
||||
std::string
|
||||
TextureTest( std::string const &Name ) {
|
||||
|
||||
auto const lookup {
|
||||
FileExists(
|
||||
{ Global.asCurrentTexturePath + Name, Name, szTexturePath + Name },
|
||||
{ ".mat", ".dds", ".tga", ".bmp" } ) };
|
||||
|
||||
return ( lookup.first + lookup.second );
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void TAnimPant::AKP_4E()
|
||||
{ // ustawienie wymiarów dla pantografu AKP-4E
|
||||
@@ -4481,7 +4493,7 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName,
|
||||
mdModel = TModelsManager::GetModel(asModel, true);
|
||||
if (ReplacableSkin != "none")
|
||||
{
|
||||
std::string nowheretexture = TextureTest( Global.asCurrentTexturePath + "nowhere" ); // na razie prymitywnie
|
||||
std::string nowheretexture = TextureTest( "nowhere" ); // na razie prymitywnie
|
||||
if( false == nowheretexture.empty() ) {
|
||||
m_materialdata.replacable_skins[ 4 ] = GfxRenderer.Fetch_Material( nowheretexture );
|
||||
}
|
||||
@@ -6204,17 +6216,6 @@ int TDynamicObject::RouteWish(TTrack *tr)
|
||||
return Mechanik ? Mechanik->CrossRoute(tr) : 0; // wg AI albo prosto
|
||||
};
|
||||
|
||||
std::string TDynamicObject::TextureTest(std::string const &name)
|
||||
{ // Ra 2015-01: sprawdzenie dostępności tekstury o podanej nazwie
|
||||
std::vector<std::string> extensions = { ".mat", ".dds", ".tga", ".bmp" };
|
||||
for( auto const &extension : extensions ) {
|
||||
if( true == FileExists( name + extension ) ) {
|
||||
return name + extension;
|
||||
}
|
||||
}
|
||||
return ""; // nie znaleziona
|
||||
};
|
||||
|
||||
void TDynamicObject::DestinationSet(std::string to, std::string numer)
|
||||
{ // ustawienie stacji docelowej oraz wymiennej tekstury 4, jeśli istnieje plik
|
||||
// w zasadzie, to każdy wagon mógłby mieć inną stację docelową
|
||||
@@ -6228,13 +6229,20 @@ void TDynamicObject::DestinationSet(std::string to, std::string numer)
|
||||
numer = Bezogonkow(numer);
|
||||
asDestination = to;
|
||||
to = Bezogonkow(to); // do szukania pliku obcinamy ogonki
|
||||
|
||||
if( true == to.empty() ) {
|
||||
to = "nowhere";
|
||||
}
|
||||
// destination textures are kept in the vehicle's directory so we point the current texture path there
|
||||
auto const currenttexturepath { Global.asCurrentTexturePath };
|
||||
Global.asCurrentTexturePath = asBaseDir;
|
||||
// now see if we can find any version of the texture
|
||||
std::vector<std::string> destinations = {
|
||||
asBaseDir + numer + "@" + MoverParameters->TypeName,
|
||||
asBaseDir + numer,
|
||||
asBaseDir + to + "@" + MoverParameters->TypeName,
|
||||
asBaseDir + to,
|
||||
asBaseDir + "nowhere" };
|
||||
numer + '@' + MoverParameters->TypeName,
|
||||
numer,
|
||||
to + '@' + MoverParameters->TypeName,
|
||||
to,
|
||||
"nowhere" + '@' + MoverParameters->TypeName,
|
||||
"nowhere" };
|
||||
|
||||
for( auto const &destination : destinations ) {
|
||||
|
||||
@@ -6244,6 +6252,8 @@ void TDynamicObject::DestinationSet(std::string to, std::string numer)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// whether we got anything, restore previous texture path
|
||||
Global.asCurrentTexturePath = currenttexturepath;
|
||||
};
|
||||
|
||||
void TDynamicObject::OverheadTrack(float o)
|
||||
|
||||
1
DynObj.h
1
DynObj.h
@@ -601,7 +601,6 @@ private:
|
||||
// zapytanie do AI, po którym segmencie skrzyżowania jechać
|
||||
int RouteWish(TTrack *tr);
|
||||
void DestinationSet(std::string to, std::string numer);
|
||||
std::string TextureTest(std::string const &name);
|
||||
void OverheadTrack(float o);
|
||||
|
||||
double MED[9][8]; // lista zmiennych do debugowania hamulca ED
|
||||
|
||||
@@ -4426,8 +4426,7 @@ double TMoverParameters::CouplerForce(int CouplerN, double dt)
|
||||
// Q: 20160714
|
||||
// oblicza sile trakcyjna lokomotywy (dla elektrowozu tez calkowity prad)
|
||||
// *************************************************************************************************
|
||||
double TMoverParameters::TractionForce(double dt)
|
||||
{
|
||||
double TMoverParameters::TractionForce( double dt ) {
|
||||
double PosRatio, dmoment, dtrans, tmp;
|
||||
|
||||
Ft = 0;
|
||||
@@ -4437,13 +4436,13 @@ double TMoverParameters::TractionForce(double dt)
|
||||
switch( EngineType ) {
|
||||
case DieselElectric: {
|
||||
if( ( true == Mains )
|
||||
&& ( true == FuelPump.is_active ) ) {
|
||||
&& ( true == FuelPump.is_active ) ) {
|
||||
|
||||
tmp = DElist[ MainCtrlPos ].RPM / 60.0;
|
||||
|
||||
if( ( true == Heating )
|
||||
&& ( HeatingPower > 0 )
|
||||
&& ( MainCtrlPosNo > MainCtrlPos ) ) {
|
||||
&& ( HeatingPower > 0 )
|
||||
&& ( MainCtrlPosNo > MainCtrlPos ) ) {
|
||||
|
||||
int i = MainCtrlPosNo;
|
||||
while( DElist[ i - 2 ].RPM / 60.0 > tmp ) {
|
||||
@@ -4460,8 +4459,8 @@ double TMoverParameters::TractionForce(double dt)
|
||||
enrot = clamp(
|
||||
enrot + ( dt / 1.25 ) * ( // TODO: equivalent of dizel_aim instead of fixed inertia
|
||||
enrot < tmp ?
|
||||
1.0 :
|
||||
-2.0 ), // NOTE: revolutions drop faster than they rise, maybe? TBD: maybe not
|
||||
1.0 :
|
||||
-2.0 ), // NOTE: revolutions drop faster than they rise, maybe? TBD: maybe not
|
||||
0.0, std::max( tmp, enrot ) );
|
||||
if( std::abs( tmp - enrot ) < 0.001 ) {
|
||||
enrot = tmp;
|
||||
@@ -4503,7 +4502,7 @@ double TMoverParameters::TractionForce(double dt)
|
||||
|
||||
case 1: { // manual
|
||||
if( ( ActiveDir != 0 )
|
||||
&& ( RList[ MainCtrlActualPos ].R > RVentCutOff ) ) {
|
||||
&& ( RList[ MainCtrlActualPos ].R > RVentCutOff ) ) {
|
||||
RventRot += ( RVentnmax - RventRot ) * RVentSpeed * dt;
|
||||
}
|
||||
else {
|
||||
@@ -4515,7 +4514,7 @@ double TMoverParameters::TractionForce(double dt)
|
||||
case 2: { // automatic
|
||||
auto const motorcurrent{ std::min<double>( ImaxHi, std::abs( Im ) ) };
|
||||
if( ( std::abs( Itot ) > RVentMinI )
|
||||
&& ( RList[ MainCtrlActualPos ].R > RVentCutOff ) ) {
|
||||
&& ( RList[ MainCtrlActualPos ].R > RVentCutOff ) ) {
|
||||
|
||||
RventRot +=
|
||||
( RVentnmax
|
||||
@@ -4525,7 +4524,7 @@ double TMoverParameters::TractionForce(double dt)
|
||||
* RVentSpeed * dt;
|
||||
}
|
||||
else if( ( DynamicBrakeType == dbrake_automatic )
|
||||
&& ( true == DynamicBrakeFlag ) ) {
|
||||
&& ( true == DynamicBrakeFlag ) ) {
|
||||
RventRot += ( RVentnmax * motorcurrent / ImaxLo - RventRot ) * RVentSpeed * dt;
|
||||
}
|
||||
else {
|
||||
@@ -4579,13 +4578,35 @@ double TMoverParameters::TractionForce(double dt)
|
||||
}
|
||||
}
|
||||
|
||||
switch( EngineType ) {
|
||||
case Dumb: {
|
||||
PosRatio = ( MainCtrlPos + ScndCtrlPos ) / ( MainCtrlPosNo + ScndCtrlPosNo + 0.01 );
|
||||
EnginePower = 1000.0 * Power * PosRatio;
|
||||
break;
|
||||
}
|
||||
case DieselEngine: {
|
||||
EnginePower = ( 2 * dizel_Mstand + dmoment ) * enrot * ( 2.0 * M_PI / 1000.0 );
|
||||
if( MainCtrlPos > 1 ) {
|
||||
// dodatkowe opory z powodu sprezarki}
|
||||
dmoment -= dizel_Mstand * ( 0.2 * enrot / dizel_nmax );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DieselElectric: {
|
||||
EnginePower = 0; // the actual calculation is done in two steps later in the method
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ActiveDir != 0)
|
||||
switch (EngineType)
|
||||
{
|
||||
case Dumb:
|
||||
{
|
||||
PosRatio = (MainCtrlPos + ScndCtrlPos) / (MainCtrlPosNo + ScndCtrlPosNo + 0.01);
|
||||
if (Mains && (ActiveDir != 0) && (CabNo != 0))
|
||||
if (Mains && (CabNo != 0))
|
||||
{
|
||||
if (Vel > 0.1)
|
||||
{
|
||||
@@ -4597,7 +4618,6 @@ double TMoverParameters::TractionForce(double dt)
|
||||
}
|
||||
else
|
||||
Ft = 0;
|
||||
EnginePower = 1000.0 * Power * PosRatio;
|
||||
break;
|
||||
} // Dumb
|
||||
|
||||
@@ -4682,11 +4702,6 @@ double TMoverParameters::TractionForce(double dt)
|
||||
|
||||
case DieselEngine:
|
||||
{
|
||||
EnginePower = ( 2 * dizel_Mstand + dmoment ) * enrot * ( 2.0 * M_PI / 1000.0 );
|
||||
if( MainCtrlPos > 1 ) {
|
||||
// dodatkowe opory z powodu sprezarki}
|
||||
dmoment -= dizel_Mstand * ( 0.2 * enrot / dizel_nmax );
|
||||
}
|
||||
Mm = dmoment; //bylo * dizel_engage
|
||||
Mw = Mm * dtrans; // dmoment i dtrans policzone przy okazji enginerotation
|
||||
Fw = Mw * 2.0 / WheelDiameter / NPoweredAxles;
|
||||
@@ -4995,9 +5010,7 @@ double TMoverParameters::TractionForce(double dt)
|
||||
}
|
||||
}
|
||||
if( true == Mains ) {
|
||||
|
||||
//tempomat
|
||||
|
||||
if (ScndCtrlPosNo > 1)
|
||||
{
|
||||
if (ScndCtrlPos != NewSpeed)
|
||||
@@ -5021,7 +5034,6 @@ double TMoverParameters::TractionForce(double dt)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dtrans = Hamulec->GetEDBCP();
|
||||
if (((DoorLeftOpened) || (DoorRightOpened)))
|
||||
DynamicBrakeFlag = true;
|
||||
@@ -5241,6 +5253,20 @@ double TMoverParameters::TractionForce(double dt)
|
||||
break;
|
||||
}
|
||||
} // case EngineType
|
||||
|
||||
switch( EngineType ) {
|
||||
case DieselElectric: {
|
||||
// rough approximation of extra effort to overcome friction etc
|
||||
auto const rpmratio{ 60.0 * enrot / DElist[ MainCtrlPosNo ].RPM };
|
||||
EnginePower += rpmratio * 0.2 * DElist[ MainCtrlPosNo ].GenPower;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return Ft;
|
||||
}
|
||||
|
||||
|
||||
76
Texture.cpp
76
Texture.cpp
@@ -767,55 +767,22 @@ texture_manager::create( std::string Filename, bool const Loadnow ) {
|
||||
Filename.erase( 0, 1 );
|
||||
}
|
||||
|
||||
std::vector<std::string> extensions { { ".dds" }, { ".tga" }, { ".bmp" }, { ".ext" } };
|
||||
|
||||
// try to locate requested texture in the databank
|
||||
auto lookup = find_in_databank( Filename + Global.szDefaultExt );
|
||||
auto lookup { find_in_databank( Filename ) };
|
||||
if( lookup != npos ) {
|
||||
// start with the default extension...
|
||||
return lookup;
|
||||
}
|
||||
else {
|
||||
// ...then try recognized file extensions other than default
|
||||
for( auto const &extension : extensions ) {
|
||||
|
||||
if( extension == Global.szDefaultExt ) {
|
||||
// we already tried this one
|
||||
continue;
|
||||
}
|
||||
lookup = find_in_databank( Filename + extension );
|
||||
if( lookup != npos ) {
|
||||
|
||||
return lookup;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we don't have the texture in the databank, check if it's on disk
|
||||
std::string filename = find_on_disk( Filename + Global.szDefaultExt );
|
||||
if( true == filename.empty() ) {
|
||||
// if the default lookup fails, try other known extensions
|
||||
for( auto const &extension : extensions ) {
|
||||
auto const disklookup { find_on_disk( Filename ) };
|
||||
|
||||
if( extension == Global.szDefaultExt ) {
|
||||
// we already tried this one
|
||||
continue;
|
||||
}
|
||||
filename = find_on_disk( Filename + extension );
|
||||
if( false == filename.empty() ) {
|
||||
// we found something, don't bother with others
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( true == filename.empty() ) {
|
||||
if( true == disklookup.first.empty() ) {
|
||||
// there's nothing matching in the databank nor on the disk, report failure
|
||||
ErrorLog( "Bad file: failed do locate texture file \"" + Filename + "\"", logtype::file );
|
||||
return npos;
|
||||
}
|
||||
|
||||
auto texture = new opengl_texture();
|
||||
texture->name = filename;
|
||||
texture->name = disklookup.first + disklookup.second;
|
||||
if( Filename.find('#') != std::string::npos ) {
|
||||
// temporary code for legacy assets -- textures with names beginning with # are to be sharpened
|
||||
traits += '#';
|
||||
@@ -823,9 +790,9 @@ texture_manager::create( std::string Filename, bool const Loadnow ) {
|
||||
texture->traits = traits;
|
||||
auto const textureindex = (texture_handle)m_textures.size();
|
||||
m_textures.emplace_back( texture, std::chrono::steady_clock::time_point() );
|
||||
m_texturemappings.emplace( filename, textureindex );
|
||||
m_texturemappings.emplace( disklookup.first, textureindex );
|
||||
|
||||
WriteLog( "Created texture object for \"" + filename + "\"", logtype::texture );
|
||||
WriteLog( "Created texture object for \"" + disklookup.first + disklookup.second + "\"", logtype::texture );
|
||||
|
||||
if( true == Loadnow ) {
|
||||
|
||||
@@ -942,7 +909,7 @@ texture_manager::info() const {
|
||||
texture_handle
|
||||
texture_manager::find_in_databank( std::string const &Texturename ) const {
|
||||
|
||||
std::vector<std::string> filenames {
|
||||
std::vector<std::string> const filenames {
|
||||
Global.asCurrentTexturePath + Texturename,
|
||||
Texturename,
|
||||
szTexturePath + Texturename };
|
||||
@@ -953,19 +920,34 @@ texture_manager::find_in_databank( std::string const &Texturename ) const {
|
||||
return lookup->second;
|
||||
}
|
||||
}
|
||||
|
||||
// all lookups failed
|
||||
return npos;
|
||||
}
|
||||
|
||||
// checks whether specified file exists.
|
||||
std::string
|
||||
std::pair<std::string, std::string>
|
||||
texture_manager::find_on_disk( std::string const &Texturename ) const {
|
||||
|
||||
return(
|
||||
FileExists( Global.asCurrentTexturePath + Texturename ) ? Global.asCurrentTexturePath + Texturename :
|
||||
FileExists( Texturename ) ? Texturename :
|
||||
FileExists( szTexturePath + Texturename ) ? szTexturePath + Texturename :
|
||||
"" );
|
||||
std::vector<std::string> const filenames {
|
||||
Global.asCurrentTexturePath + Texturename,
|
||||
Texturename,
|
||||
szTexturePath + Texturename };
|
||||
|
||||
auto lookup =
|
||||
FileExists(
|
||||
filenames,
|
||||
{ Global.szDefaultExt } );
|
||||
|
||||
if( false == lookup.first.empty() ) {
|
||||
return lookup;
|
||||
}
|
||||
|
||||
// if the first attempt fails, try entire extension list
|
||||
// NOTE: slightly wasteful as it means preferred extension is tested twice, but, eh
|
||||
return (
|
||||
FileExists(
|
||||
filenames,
|
||||
{ ".dds", ".tga", ".bmp", ".ext" } ) );
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -21,6 +21,8 @@ struct opengl_texture {
|
||||
static DDPIXELFORMAT deserialize_ddpf(std::istream&);
|
||||
static DDSCAPS2 deserialize_ddscaps(std::istream&);
|
||||
|
||||
// constructors
|
||||
opengl_texture() = default;
|
||||
// methods
|
||||
void
|
||||
load();
|
||||
@@ -120,7 +122,7 @@ private:
|
||||
texture_handle
|
||||
find_in_databank( std::string const &Texturename ) const;
|
||||
// checks whether specified file exists. returns name of the located file, or empty string.
|
||||
std::string
|
||||
std::pair<std::string, std::string>
|
||||
find_on_disk( std::string const &Texturename ) const;
|
||||
void
|
||||
delete_textures();
|
||||
|
||||
56
Train.cpp
56
Train.cpp
@@ -5882,6 +5882,10 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
|
||||
sound->offset( nullvector );
|
||||
sound->owner( DynamicObject );
|
||||
}
|
||||
// reset view angles
|
||||
pMechViewAngle = { 0.0, 0.0 };
|
||||
Global.pCamera->Pitch = pMechViewAngle.x;
|
||||
Global.pCamera->Yaw = pMechViewAngle.y;
|
||||
|
||||
pyScreens.reset(this);
|
||||
pyScreens.setLookupPath(DynamicObject->asBaseDir);
|
||||
@@ -5934,41 +5938,59 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
|
||||
{
|
||||
// jeśli znaleziony wpis kabiny
|
||||
Cabine[cabindex].Load(*parser);
|
||||
// NOTE: the next part is likely to break if sitpos doesn't follow pos
|
||||
// NOTE: the position and angle definitions depend on strict entry order
|
||||
// TODO: refactor into more flexible arrangement
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
if( token == std::string( "driver" + std::to_string( cabindex ) + "angle:" ) ) {
|
||||
// camera view angle
|
||||
parser->getTokens( 2, false );
|
||||
// angle is specified in degrees but internally stored in radians
|
||||
glm::vec2 viewangle;
|
||||
*parser
|
||||
>> viewangle.y // yaw first, then pitch
|
||||
>> viewangle.x;
|
||||
pMechViewAngle = glm::radians( viewangle );
|
||||
Global.pCamera->Pitch = pMechViewAngle.x;
|
||||
Global.pCamera->Yaw = pMechViewAngle.y;
|
||||
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
}
|
||||
if (token == std::string("driver" + std::to_string(cabindex) + "pos:"))
|
||||
{
|
||||
// pozycja poczatkowa maszynisty
|
||||
parser->getTokens(3, false);
|
||||
*parser >> pMechOffset.x >> pMechOffset.y >> pMechOffset.z;
|
||||
pMechSittingPosition.x = pMechOffset.x;
|
||||
pMechSittingPosition.y = pMechOffset.y;
|
||||
pMechSittingPosition.z = pMechOffset.z;
|
||||
*parser
|
||||
>> pMechOffset.x
|
||||
>> pMechOffset.y
|
||||
>> pMechOffset.z;
|
||||
pMechSittingPosition = pMechOffset;
|
||||
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
}
|
||||
// ABu: pozycja siedzaca mechanika
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
if (token == std::string("driver" + std::to_string(cabindex) + "sitpos:"))
|
||||
{
|
||||
// ABu 180404 pozycja siedzaca maszynisty
|
||||
parser->getTokens(3, false);
|
||||
*parser >> pMechSittingPosition.x >> pMechSittingPosition.y >> pMechSittingPosition.z;
|
||||
parse = true;
|
||||
*parser
|
||||
>> pMechSittingPosition.x
|
||||
>> pMechSittingPosition.y
|
||||
>> pMechSittingPosition.z;
|
||||
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
}
|
||||
// else parse=false;
|
||||
do
|
||||
{
|
||||
// ABu: wstawione warunki, wczesniej tylko to:
|
||||
// str=Parser->GetNextSymbol().LowerCase();
|
||||
if (parse == true) {
|
||||
|
||||
do {
|
||||
if( parse == true ) {
|
||||
token = "";
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
parse = true;
|
||||
}
|
||||
// inicjacja kabiny
|
||||
|
||||
1
Train.h
1
Train.h
@@ -592,6 +592,7 @@ public: // reszta może by?publiczna
|
||||
|
||||
Math3D::vector3 pMechSittingPosition; // ABu 180404
|
||||
Math3D::vector3 MirrorPosition(bool lewe);
|
||||
glm::vec2 pMechViewAngle { 0.0, 0.0 }; // camera pitch and yaw values, preserved while in external view
|
||||
|
||||
private:
|
||||
double fBlinkTimer;
|
||||
|
||||
36
World.cpp
36
World.cpp
@@ -607,6 +607,7 @@ void TWorld::InOutKey( bool const Near )
|
||||
if (Train) {
|
||||
// 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->Dynamic()->bDisplayCab = false;
|
||||
DistantView( Near );
|
||||
}
|
||||
@@ -618,9 +619,8 @@ void TWorld::InOutKey( bool const Near )
|
||||
if (Train)
|
||||
{
|
||||
Train->Dynamic()->bDisplayCab = true;
|
||||
Train->Dynamic()->ABuSetModelShake(
|
||||
Math3D::vector3(0, 0, 0)); // zerowanie przesunięcia przed powrotem?
|
||||
// Camera.Stop(); //zatrzymanie ruchu
|
||||
// zerowanie przesunięcia przed powrotem?
|
||||
Train->Dynamic()->ABuSetModelShake( { 0, 0, 0 } );
|
||||
Train->MechStop();
|
||||
FollowView(); // na pozycję mecha
|
||||
}
|
||||
@@ -694,14 +694,12 @@ void TWorld::FollowView(bool wycisz) {
|
||||
// tu ustawić nową, bo od niej liczą się odległości
|
||||
Global.pCameraPosition = Camera.Pos;
|
||||
}
|
||||
else if (Train)
|
||||
{ // korekcja ustawienia w kabinie - OK
|
||||
if( wycisz ) {
|
||||
// wyciszenie dźwięków z poprzedniej pozycji
|
||||
// trzymanie prawego w kabinie daje marny efekt
|
||||
// TODO: re-implement, old one kinda didn't really work
|
||||
}
|
||||
else if (Train) {
|
||||
Camera.Pos = Train->pMechPosition;
|
||||
// potentially restore cached camera angles
|
||||
Camera.Pitch = Train->pMechViewAngle.x;
|
||||
Camera.Yaw = Train->pMechViewAngle.y;
|
||||
|
||||
Camera.Roll = std::atan(Train->pMechShake.x * Train->fMechRoll); // hustanie kamery na boki
|
||||
Camera.Pitch -= 0.5 * std::atan(Train->vMechVelocity.z * Train->fMechPitch); // hustanie kamery przod tyl
|
||||
|
||||
@@ -946,6 +944,14 @@ TWorld::Update_Camera( double const Deltatime ) {
|
||||
|
||||
if( DebugCameraFlag ) { DebugCamera.Update(); }
|
||||
else { Camera.Update(); } // uwzględnienie ruchu wywołanego klawiszami
|
||||
|
||||
if( ( false == FreeFlyModeFlag )
|
||||
&& ( false == Global.CabWindowOpen )
|
||||
&& ( Train != nullptr ) ) {
|
||||
// cache cab camera view angles in case of view type switch
|
||||
Train->pMechViewAngle = { Camera.Pitch, Camera.Yaw };
|
||||
}
|
||||
|
||||
// reset window state, it'll be set again if applicable in a check below
|
||||
Global.CabWindowOpen = false;
|
||||
|
||||
@@ -954,7 +960,7 @@ TWorld::Update_Camera( double const Deltatime ) {
|
||||
&& ( false == DebugCameraFlag ) ) {
|
||||
// jeśli jazda w kabinie, przeliczyć trzeba parametry kamery
|
||||
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 )
|
||||
&& ( ( glfwGetKey( Global.window, GLFW_KEY_LEFT ) == GLFW_TRUE )
|
||||
@@ -982,6 +988,11 @@ TWorld::Update_Camera( double const Deltatime ) {
|
||||
}
|
||||
else {
|
||||
// patrzenie standardowe
|
||||
// potentially restore view angle after returning from external view
|
||||
// TODO: mirror view toggle as separate method
|
||||
Camera.Pitch = Train->pMechViewAngle.x;
|
||||
Camera.Yaw = Train->pMechViewAngle.y;
|
||||
|
||||
Camera.Pos = Train->GetWorldMechPosition(); // Train.GetPosition1();
|
||||
if( !Global.iPause ) {
|
||||
// podczas pauzy nie przeliczać kątów przypadkowymi wartościami
|
||||
@@ -991,8 +1002,8 @@ TWorld::Update_Camera( double const Deltatime ) {
|
||||
// Ra: tu jest uciekanie kamery w górę!!!
|
||||
Camera.Pitch -= 0.5 * atan( Train->vMechVelocity.z * Train->fMechPitch );
|
||||
}
|
||||
// ABu011104: rzucanie pudlem
|
||||
/*
|
||||
// ABu011104: rzucanie pudlem
|
||||
vector3 temp;
|
||||
if( abs( Train->pMechShake.y ) < 0.25 )
|
||||
temp = vector3( 0, 0, 6 * Train->pMechShake.y );
|
||||
@@ -1004,7 +1015,6 @@ TWorld::Update_Camera( double const Deltatime ) {
|
||||
Controlled->ABuSetModelShake( temp );
|
||||
// ABu: koniec rzucania
|
||||
*/
|
||||
|
||||
if( Train->Dynamic()->MoverParameters->ActiveCab == 0 )
|
||||
Camera.LookAt = Train->GetWorldMechPosition() + Train->GetDirection() * 5.0; // gdy w korytarzu
|
||||
else // patrzenie w kierunku osi pojazdu, z uwzględnieniem kabiny
|
||||
|
||||
21
audio.cpp
21
audio.cpp
@@ -210,8 +210,9 @@ buffer_manager::emplace( std::string Filename ) {
|
||||
m_buffers.emplace_back( Filename );
|
||||
|
||||
// NOTE: we store mapping without file type extension, to simplify lookups
|
||||
erase_extension( Filename );
|
||||
m_buffermappings.emplace(
|
||||
Filename.erase( Filename.rfind( '.' ) ),
|
||||
Filename,
|
||||
handle );
|
||||
|
||||
return handle;
|
||||
@@ -220,26 +221,22 @@ buffer_manager::emplace( std::string Filename ) {
|
||||
audio::buffer_handle
|
||||
buffer_manager::find_buffer( std::string const &Buffername ) const {
|
||||
|
||||
auto lookup = m_buffermappings.find( Buffername );
|
||||
if( lookup != m_buffermappings.end() )
|
||||
auto const lookup = m_buffermappings.find( Buffername );
|
||||
if( lookup != std::end( m_buffermappings ) )
|
||||
return lookup->second;
|
||||
else
|
||||
return null_handle;
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
buffer_manager::find_file( std::string const &Filename ) const {
|
||||
|
||||
std::vector<std::string> const extensions { ".ogg", ".flac", ".wav" };
|
||||
auto const lookup {
|
||||
FileExists(
|
||||
{ Filename },
|
||||
{ ".ogg", ".flac", ".wav" } ) };
|
||||
|
||||
for( auto const &extension : extensions ) {
|
||||
if( FileExists( Filename + extension ) ) {
|
||||
// valid name on success
|
||||
return Filename + extension;
|
||||
}
|
||||
}
|
||||
return {}; // empty string on failure
|
||||
return lookup.first + lookup.second;
|
||||
}
|
||||
|
||||
} // audio
|
||||
|
||||
31
material.cpp
31
material.cpp
@@ -117,23 +117,21 @@ material_manager::create( std::string const &Filename, bool const Loadnow ) {
|
||||
filename.erase( 0, 1 );
|
||||
}
|
||||
|
||||
filename += ".mat";
|
||||
|
||||
// try to locate requested material in the databank
|
||||
auto const databanklookup = find_in_databank( filename );
|
||||
auto const databanklookup { find_in_databank( filename ) };
|
||||
if( databanklookup != null_handle ) {
|
||||
return databanklookup;
|
||||
}
|
||||
// if this fails, try to look for it on disk
|
||||
opengl_material material;
|
||||
auto const disklookup = find_on_disk( filename );
|
||||
if( disklookup != "" ) {
|
||||
cParser materialparser( disklookup, cParser::buffer_FILE );
|
||||
auto const disklookup { find_on_disk( filename ) };
|
||||
if( false == disklookup.first.empty() ) {
|
||||
cParser materialparser( disklookup.first + disklookup.second, cParser::buffer_FILE );
|
||||
if( false == material.deserialize( materialparser, Loadnow ) ) {
|
||||
// deserialization failed but the .mat file does exist, so we give up at this point
|
||||
return null_handle;
|
||||
}
|
||||
material.name = disklookup;
|
||||
material.name = disklookup.first;
|
||||
}
|
||||
else {
|
||||
// if there's no .mat file, this could be legacy method of referring just to diffuse texture directly, make a material out of it in such case
|
||||
@@ -145,7 +143,7 @@ material_manager::create( std::string const &Filename, bool const Loadnow ) {
|
||||
// use texture path and name to tell the newly created materials apart
|
||||
filename = GfxRenderer.Texture( material.texture1 ).name;
|
||||
erase_extension( filename );
|
||||
material.name = filename + ".mat";
|
||||
material.name = filename;
|
||||
material.has_alpha = GfxRenderer.Texture( material.texture1 ).has_alpha;
|
||||
}
|
||||
|
||||
@@ -159,7 +157,7 @@ material_manager::create( std::string const &Filename, bool const Loadnow ) {
|
||||
material_handle
|
||||
material_manager::find_in_databank( std::string const &Materialname ) const {
|
||||
|
||||
std::vector<std::string> filenames {
|
||||
std::vector<std::string> const filenames {
|
||||
Global.asCurrentTexturePath + Materialname,
|
||||
Materialname,
|
||||
szTexturePath + Materialname };
|
||||
@@ -170,20 +168,19 @@ material_manager::find_in_databank( std::string const &Materialname ) const {
|
||||
return lookup->second;
|
||||
}
|
||||
}
|
||||
|
||||
// all lookups failed
|
||||
return null_handle;
|
||||
}
|
||||
|
||||
// checks whether specified file exists.
|
||||
// NOTE: this is direct copy of the method used by texture manager. TBD, TODO: refactor into common routine?
|
||||
std::string
|
||||
// NOTE: technically could be static, but we might want to switch from global texture path to instance-specific at some point
|
||||
std::pair<std::string, std::string>
|
||||
material_manager::find_on_disk( std::string const &Materialname ) const {
|
||||
|
||||
return(
|
||||
FileExists( Global.asCurrentTexturePath + Materialname ) ? Global.asCurrentTexturePath + Materialname :
|
||||
FileExists( Materialname ) ? Materialname :
|
||||
FileExists( szTexturePath + Materialname ) ? szTexturePath + Materialname :
|
||||
"" );
|
||||
return (
|
||||
FileExists(
|
||||
{ Global.asCurrentTexturePath + Materialname, Materialname, szTexturePath + Materialname },
|
||||
{ ".mat" } ) );
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -25,6 +25,9 @@ struct opengl_material {
|
||||
bool has_alpha { false }; // alpha state, calculated from presence of alpha in texture1
|
||||
std::string name;
|
||||
|
||||
// constructors
|
||||
opengl_material() = default;
|
||||
|
||||
// methods
|
||||
bool
|
||||
deserialize( cParser &Input, bool const Loadnow );
|
||||
@@ -59,7 +62,7 @@ private:
|
||||
material_handle
|
||||
find_in_databank( std::string const &Materialname ) const;
|
||||
// checks whether specified file exists. returns name of the located file, or empty string.
|
||||
std::string
|
||||
std::pair<std::string, std::string>
|
||||
find_on_disk( std::string const &Materialname ) const;
|
||||
// members:
|
||||
material_sequence m_materials;
|
||||
|
||||
@@ -330,6 +330,20 @@ FileExists( std::string const &Filename ) {
|
||||
return( true == file.is_open() );
|
||||
}
|
||||
|
||||
std::pair<std::string, std::string>
|
||||
FileExists( std::vector<std::string> const &Names, std::vector<std::string> const &Extensions ) {
|
||||
|
||||
for( auto const &name : Names ) {
|
||||
for( auto const &extension : Extensions ) {
|
||||
if( FileExists( name + extension ) ) {
|
||||
return { name, extension };
|
||||
}
|
||||
}
|
||||
}
|
||||
// nothing found
|
||||
return { {}, {} };
|
||||
}
|
||||
|
||||
// returns time of last modification for specified file
|
||||
std::time_t
|
||||
last_modified( std::string const &Filename ) {
|
||||
|
||||
@@ -179,6 +179,8 @@ extract_value( bool &Variable, std::string const &Key, std::string const &Input,
|
||||
|
||||
bool FileExists( std::string const &Filename );
|
||||
|
||||
std::pair<std::string, std::string> FileExists( std::vector<std::string> const &Names, std::vector<std::string> const &Extensions );
|
||||
|
||||
// returns time of last modification for specified file
|
||||
std::time_t last_modified( std::string const &Filename );
|
||||
|
||||
|
||||
Reference in New Issue
Block a user