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:
tmj-fstate
2018-05-27 02:31:40 +02:00
parent aa520aa3e7
commit 2c1c29600e
17 changed files with 272 additions and 169 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
#pragma once
#define VERSION_MAJOR 18
#define VERSION_MINOR 521
#define VERSION_MINOR 527
#define VERSION_REVISION 0