mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 16:19:19 +02:00
audio subsystem: openal emitter, minor audio fixes
This commit is contained in:
@@ -46,6 +46,7 @@ void TButton::Load(cParser &Parser, TModel3d *pModel1, TModel3d *pModel2) {
|
|||||||
else {
|
else {
|
||||||
// new, block type config
|
// new, block type config
|
||||||
// TODO: rework the base part into yaml-compatible flow style mapping
|
// TODO: rework the base part into yaml-compatible flow style mapping
|
||||||
|
submodelname = Parser.getToken<std::string>( false );
|
||||||
while( true == Load_mapping( Parser ) ) {
|
while( true == Load_mapping( Parser ) ) {
|
||||||
; // all work done by while()
|
; // all work done by while()
|
||||||
}
|
}
|
||||||
|
|||||||
73
DynObj.cpp
73
DynObj.cpp
@@ -3354,6 +3354,7 @@ bool TDynamicObject::Update(double dt, double dt1)
|
|||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
#ifdef EU07_USE_OLD_SOUNDCODE
|
||||||
rsDoorOpen.Play(1, 0, MechInside, vPosition);
|
rsDoorOpen.Play(1, 0, MechInside, vPosition);
|
||||||
#else
|
#else
|
||||||
|
rsDoorClose.stop();
|
||||||
rsDoorOpen.play();
|
rsDoorOpen.play();
|
||||||
#endif
|
#endif
|
||||||
dDoorMoveL += dt1 * 0.5 * MoverParameters->DoorOpenSpeed;
|
dDoorMoveL += dt1 * 0.5 * MoverParameters->DoorOpenSpeed;
|
||||||
@@ -3363,6 +3364,7 @@ bool TDynamicObject::Update(double dt, double dt1)
|
|||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
#ifdef EU07_USE_OLD_SOUNDCODE
|
||||||
rsDoorClose.Play(1, 0, MechInside, vPosition);
|
rsDoorClose.Play(1, 0, MechInside, vPosition);
|
||||||
#else
|
#else
|
||||||
|
rsDoorOpen.stop();
|
||||||
rsDoorClose.play();
|
rsDoorClose.play();
|
||||||
#endif
|
#endif
|
||||||
dDoorMoveL -= dt1 * MoverParameters->DoorCloseSpeed;
|
dDoorMoveL -= dt1 * MoverParameters->DoorCloseSpeed;
|
||||||
@@ -3374,6 +3376,7 @@ bool TDynamicObject::Update(double dt, double dt1)
|
|||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
#ifdef EU07_USE_OLD_SOUNDCODE
|
||||||
rsDoorOpen.Play(1, 0, MechInside, vPosition);
|
rsDoorOpen.Play(1, 0, MechInside, vPosition);
|
||||||
#else
|
#else
|
||||||
|
rsDoorClose.stop();
|
||||||
rsDoorOpen.play();
|
rsDoorOpen.play();
|
||||||
#endif
|
#endif
|
||||||
dDoorMoveR += dt1 * 0.5 * MoverParameters->DoorOpenSpeed;
|
dDoorMoveR += dt1 * 0.5 * MoverParameters->DoorOpenSpeed;
|
||||||
@@ -3383,6 +3386,7 @@ bool TDynamicObject::Update(double dt, double dt1)
|
|||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
#ifdef EU07_USE_OLD_SOUNDCODE
|
||||||
rsDoorClose.Play(1, 0, MechInside, vPosition);
|
rsDoorClose.Play(1, 0, MechInside, vPosition);
|
||||||
#else
|
#else
|
||||||
|
rsDoorOpen.stop();
|
||||||
rsDoorClose.play();
|
rsDoorClose.play();
|
||||||
#endif
|
#endif
|
||||||
dDoorMoveR -= dt1 * MoverParameters->DoorCloseSpeed;
|
dDoorMoveR -= dt1 * MoverParameters->DoorCloseSpeed;
|
||||||
@@ -3849,16 +3853,70 @@ void TDynamicObject::RenderSounds() {
|
|||||||
if (GetVelocity() == 0)
|
if (GetVelocity() == 0)
|
||||||
rsDerailment.Stop();
|
rsDerailment.Stop();
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
// McZapkie! - dzwiek compressor.wav tylko gdy dziala sprezarka
|
||||||
|
if( MoverParameters->VeselVolume != 0 ) {
|
||||||
|
|
||||||
|
if( MoverParameters->TrainType != dt_PseudoDiesel ) {
|
||||||
|
// NBMX dzwiek przetwornicy
|
||||||
|
if( MoverParameters->ConverterFlag ) {
|
||||||
|
sConverter.play();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sConverter.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
}
|
||||||
|
|
||||||
|
if( MoverParameters->CompressorFlag ) {
|
||||||
|
sCompressor.play();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sCompressor.stop();
|
||||||
|
}
|
||||||
|
if( MoverParameters->PantCompFlag ) {
|
||||||
|
// Winger 160404 - dzwiek malej sprezarki
|
||||||
|
sSmallCompressor.play();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sSmallCompressor.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( TestFlag( MoverParameters->WarningSignal, 1 ) ) {
|
||||||
|
sHorn1.play();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sHorn1.stop();
|
||||||
|
}
|
||||||
|
if( TestFlag( MoverParameters->WarningSignal, 2 ) ) {
|
||||||
|
sHorn2.play();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sHorn2.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( MoverParameters->DoorClosureWarning ) {
|
||||||
|
if( MoverParameters->DepartureSignal ) {
|
||||||
|
// NBMX sygnal odjazdu
|
||||||
|
// MC: pod warunkiem ze jest zdefiniowane w chk
|
||||||
|
sDepartureSignal.play();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sDepartureSignal.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// McZapkie-250202
|
// McZapkie-250202
|
||||||
// wczytywanie pliku z danymi multimedialnymi (dzwieki)
|
// wczytywanie pliku z danymi multimedialnymi (dzwieki)
|
||||||
void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
|
void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, std::string ReplacableSkin ) {
|
||||||
std::string ReplacableSkin)
|
|
||||||
{
|
|
||||||
double dSDist;
|
double dSDist;
|
||||||
// asBaseDir=BaseDir;
|
|
||||||
Global::asCurrentDynamicPath = BaseDir;
|
Global::asCurrentDynamicPath = BaseDir;
|
||||||
std::string asFileName = BaseDir + TypeName + ".mmd";
|
std::string asFileName = BaseDir + TypeName + ".mmd";
|
||||||
std::string asLoadName;
|
std::string asLoadName;
|
||||||
@@ -3898,8 +3956,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
|
|||||||
}
|
}
|
||||||
m_materialdata.multi_textures = clamp( m_materialdata.multi_textures, 0, 1 ); // na razie ustawiamy na 1
|
m_materialdata.multi_textures = clamp( m_materialdata.multi_textures, 0, 1 ); // na razie ustawiamy na 1
|
||||||
}
|
}
|
||||||
asModel = BaseDir + asModel; // McZapkie 2002-07-20: dynamics maja swoje
|
asModel = BaseDir + asModel; // McZapkie 2002-07-20: dynamics maja swoje modele w dynamics/basedir
|
||||||
// modele w dynamics/basedir
|
|
||||||
Global::asCurrentTexturePath = BaseDir; // biezaca sciezka do tekstur to dynamic/...
|
Global::asCurrentTexturePath = BaseDir; // biezaca sciezka do tekstur to dynamic/...
|
||||||
mdModel = TModelsManager::GetModel(asModel, true);
|
mdModel = TModelsManager::GetModel(asModel, true);
|
||||||
assert( mdModel != nullptr ); // TODO: handle this more gracefully than all going to shit
|
assert( mdModel != nullptr ); // TODO: handle this more gracefully than all going to shit
|
||||||
@@ -4757,9 +4814,8 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if( token == "curve:" ) {
|
else if( token == "curve:" ) {
|
||||||
|
|
||||||
double attenuation;
|
|
||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
#ifdef EU07_USE_OLD_SOUNDCODE
|
||||||
|
double attenuation;
|
||||||
parser.getTokens( 2, false );
|
parser.getTokens( 2, false );
|
||||||
parser
|
parser
|
||||||
>> token
|
>> token
|
||||||
@@ -4959,6 +5015,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
|
|||||||
mdLowPolyInt->Init();
|
mdLowPolyInt->Init();
|
||||||
|
|
||||||
Global::asCurrentTexturePath = szTexturePath; // kiedyś uproszczone wnętrze mieszało tekstury nieba
|
Global::asCurrentTexturePath = szTexturePath; // kiedyś uproszczone wnętrze mieszało tekstury nieba
|
||||||
|
Global::asCurrentDynamicPath = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
32
Globals.cpp
32
Globals.cpp
@@ -53,19 +53,15 @@ std::string Global::szTexturesDDS = ".dds"; // lista tekstur od DDS
|
|||||||
int Global::iPause = 0; // 0x10; // globalna pauza ruchu
|
int Global::iPause = 0; // 0x10; // globalna pauza ruchu
|
||||||
bool Global::bActive = true; // czy jest aktywnym oknem
|
bool Global::bActive = true; // czy jest aktywnym oknem
|
||||||
TWorld *Global::pWorld = NULL;
|
TWorld *Global::pWorld = NULL;
|
||||||
cParser *Global::pParser = NULL;
|
|
||||||
TCamera *Global::pCamera = NULL; // parametry kamery
|
TCamera *Global::pCamera = NULL; // parametry kamery
|
||||||
TDynamicObject *Global::pUserDynamic = NULL; // pojazd użytkownika, renderowany bez trzęsienia
|
|
||||||
TTranscripts Global::tranTexts; // obiekt obsługujący stenogramy dźwięków na ekranie
|
TTranscripts Global::tranTexts; // obiekt obsługujący stenogramy dźwięków na ekranie
|
||||||
float4 Global::UITextColor = float4( 225.0 / 255.0f, 225.0f / 255.0f, 225.0f / 255.0f, 1.0f );
|
float4 Global::UITextColor = float4( 225.0 / 255.0f, 225.0f / 255.0f, 225.0f / 255.0f, 1.0f );
|
||||||
|
|
||||||
// parametry scenerii
|
|
||||||
vector3 Global::pCameraPosition;
|
vector3 Global::pCameraPosition;
|
||||||
vector3 Global::DebugCameraPosition;
|
vector3 Global::DebugCameraPosition;
|
||||||
double Global::pCameraRotation;
|
|
||||||
double Global::pCameraRotationDeg;
|
|
||||||
std::vector<vector3> Global::FreeCameraInit;
|
std::vector<vector3> Global::FreeCameraInit;
|
||||||
std::vector<vector3> Global::FreeCameraInitAngle;
|
std::vector<vector3> Global::FreeCameraInitAngle;
|
||||||
|
// parametry scenerii
|
||||||
GLfloat Global::FogColor[] = {0.6f, 0.7f, 0.8f};
|
GLfloat Global::FogColor[] = {0.6f, 0.7f, 0.8f};
|
||||||
double Global::fFogStart = 1700;
|
double Global::fFogStart = 1700;
|
||||||
double Global::fFogEnd = 2000;
|
double Global::fFogEnd = 2000;
|
||||||
@@ -127,8 +123,6 @@ bool Global::bGlutFont = false; // czy tekst generowany przez GLUT32.DLL
|
|||||||
int Global::iConvertModels{ 0 }; // temporary override, to prevent generation of .e3d not compatible with old exe
|
int Global::iConvertModels{ 0 }; // temporary override, to prevent generation of .e3d not compatible with old exe
|
||||||
int Global::iSlowMotionMask = -1; // maska wyłączanych właściwości dla zwiększenia FPS
|
int Global::iSlowMotionMask = -1; // maska wyłączanych właściwości dla zwiększenia FPS
|
||||||
// bool Global::bTerrainCompact=true; //czy zapisać teren w pliku
|
// bool Global::bTerrainCompact=true; //czy zapisać teren w pliku
|
||||||
TAnimModel *Global::pTerrainCompact = NULL; // do zapisania terenu w pliku
|
|
||||||
std::string Global::asTerrainModel = ""; // nazwa obiektu terenu do zapisania w pliku
|
|
||||||
double Global::fFpsAverage = 20.0; // oczekiwana wartosć FPS
|
double Global::fFpsAverage = 20.0; // oczekiwana wartosć FPS
|
||||||
double Global::fFpsDeviation = 5.0; // odchylenie standardowe FPS
|
double Global::fFpsDeviation = 5.0; // odchylenie standardowe FPS
|
||||||
double Global::fFpsMin = 30.0; // dolna granica FPS, przy której promień scenerii będzie zmniejszany
|
double Global::fFpsMin = 30.0; // dolna granica FPS, przy której promień scenerii będzie zmniejszany
|
||||||
@@ -965,16 +959,6 @@ void Global::SetCameraPosition(vector3 pNewCameraPosition)
|
|||||||
pCameraPosition = pNewCameraPosition;
|
pCameraPosition = pNewCameraPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Global::SetCameraRotation(double Yaw)
|
|
||||||
{ // ustawienie bezwzględnego kierunku kamery z korekcją do przedziału <-M_PI,M_PI>
|
|
||||||
pCameraRotation = Yaw;
|
|
||||||
while (pCameraRotation < -M_PI)
|
|
||||||
pCameraRotation += 2 * M_PI;
|
|
||||||
while (pCameraRotation > M_PI)
|
|
||||||
pCameraRotation -= 2 * M_PI;
|
|
||||||
pCameraRotationDeg = pCameraRotation * 180.0 / M_PI;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Global::TrainDelete(TDynamicObject *d)
|
void Global::TrainDelete(TDynamicObject *d)
|
||||||
{ // usunięcie pojazdu prowadzonego przez użytkownika
|
{ // usunięcie pojazdu prowadzonego przez użytkownika
|
||||||
if (pWorld)
|
if (pWorld)
|
||||||
@@ -983,20 +967,6 @@ void Global::TrainDelete(TDynamicObject *d)
|
|||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool Global::DoEvents()
|
|
||||||
{ // wywoływać czasem, żeby nie robił wrażenia zawieszonego
|
|
||||||
MSG msg;
|
|
||||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
|
||||||
{
|
|
||||||
if (msg.message == WM_QUIT)
|
|
||||||
return FALSE;
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
TTranscripts::TTranscripts()
|
TTranscripts::TTranscripts()
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|||||||
22
Globals.h
22
Globals.h
@@ -10,10 +10,8 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <Windows.h>
|
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
#include "glfw/glfw3.h"
|
|
||||||
#include "gl/glew.h"
|
|
||||||
#include "dumb3d.h"
|
#include "dumb3d.h"
|
||||||
|
|
||||||
// definicje klawiszy
|
// definicje klawiszy
|
||||||
@@ -113,16 +111,6 @@ const int k_WalkMode = 73;
|
|||||||
int const k_DimHeadlights = 74;
|
int const k_DimHeadlights = 74;
|
||||||
const int MaxKeys = 75;
|
const int MaxKeys = 75;
|
||||||
|
|
||||||
// klasy dla wskaźników globalnych
|
|
||||||
/*
|
|
||||||
class TGround;
|
|
||||||
class TWorld;
|
|
||||||
class TCamera;
|
|
||||||
class TDynamicObject;
|
|
||||||
class TAnimModel; // obiekt terenu
|
|
||||||
class cParser; // nowy (powolny!) parser
|
|
||||||
class TEvent;
|
|
||||||
*/
|
|
||||||
class TTranscript
|
class TTranscript
|
||||||
{ // klasa obsługująca linijkę napisu do dźwięku
|
{ // klasa obsługująca linijkę napisu do dźwięku
|
||||||
public:
|
public:
|
||||||
@@ -159,9 +147,7 @@ public:
|
|||||||
static void InitKeys();
|
static void InitKeys();
|
||||||
inline static Math3D::vector3 GetCameraPosition() { return pCameraPosition; };
|
inline static Math3D::vector3 GetCameraPosition() { return pCameraPosition; };
|
||||||
static void SetCameraPosition(Math3D::vector3 pNewCameraPosition);
|
static void SetCameraPosition(Math3D::vector3 pNewCameraPosition);
|
||||||
static void SetCameraRotation(double Yaw);
|
|
||||||
static void TrainDelete(TDynamicObject *d);
|
static void TrainDelete(TDynamicObject *d);
|
||||||
static bool DoEvents();
|
|
||||||
static std::string Bezogonkow(std::string str, bool _ = false);
|
static std::string Bezogonkow(std::string str, bool _ = false);
|
||||||
static double Min0RSpeed(double vel1, double vel2);
|
static double Min0RSpeed(double vel1, double vel2);
|
||||||
|
|
||||||
@@ -170,8 +156,6 @@ public:
|
|||||||
static bool RealisticControlMode; // controls ability to steer the vehicle from outside views
|
static bool RealisticControlMode; // controls ability to steer the vehicle from outside views
|
||||||
static Math3D::vector3 pCameraPosition; // pozycja kamery w świecie
|
static Math3D::vector3 pCameraPosition; // pozycja kamery w świecie
|
||||||
static Math3D::vector3 DebugCameraPosition; // pozycja kamery w świecie
|
static Math3D::vector3 DebugCameraPosition; // pozycja kamery w świecie
|
||||||
static double pCameraRotation; // kierunek bezwzględny kamery w świecie: 0=północ, 90°=zachód (-azymut)
|
|
||||||
static double pCameraRotationDeg; // w stopniach, dla animacji billboard
|
|
||||||
static std::vector<Math3D::vector3> FreeCameraInit; // pozycje kamery
|
static std::vector<Math3D::vector3> FreeCameraInit; // pozycje kamery
|
||||||
static std::vector<Math3D::vector3> FreeCameraInitAngle;
|
static std::vector<Math3D::vector3> FreeCameraInitAngle;
|
||||||
static int iWindowWidth;
|
static int iWindowWidth;
|
||||||
@@ -272,16 +256,12 @@ public:
|
|||||||
static bool bHideConsole; // hunter-271211: ukrywanie konsoli
|
static bool bHideConsole; // hunter-271211: ukrywanie konsoli
|
||||||
|
|
||||||
static TWorld *pWorld; // wskaźnik na świat do usuwania pojazdów
|
static TWorld *pWorld; // wskaźnik na świat do usuwania pojazdów
|
||||||
static TAnimModel *pTerrainCompact; // obiekt terenu do ewentualnego zapisania w pliku
|
|
||||||
static std::string asTerrainModel; // nazwa obiektu terenu do zapisania w pliku
|
|
||||||
static bool bRollFix; // czy wykonać przeliczanie przechyłki
|
static bool bRollFix; // czy wykonać przeliczanie przechyłki
|
||||||
static cParser *pParser;
|
|
||||||
static double fFpsAverage; // oczekiwana wartosć FPS
|
static double fFpsAverage; // oczekiwana wartosć FPS
|
||||||
static double fFpsDeviation; // odchylenie standardowe FPS
|
static double fFpsDeviation; // odchylenie standardowe FPS
|
||||||
static double fFpsMin; // dolna granica FPS, przy której promień scenerii będzie zmniejszany
|
static double fFpsMin; // dolna granica FPS, przy której promień scenerii będzie zmniejszany
|
||||||
static double fFpsMax; // górna granica FPS, przy której promień scenerii będzie zwiększany
|
static double fFpsMax; // górna granica FPS, przy której promień scenerii będzie zwiększany
|
||||||
static TCamera *pCamera; // parametry kamery
|
static TCamera *pCamera; // parametry kamery
|
||||||
static TDynamicObject *pUserDynamic; // pojazd użytkownika, renderowany bez trzęsienia
|
|
||||||
static double fCalibrateIn[6][6]; // parametry kalibracyjne wejść z pulpitu
|
static double fCalibrateIn[6][6]; // parametry kalibracyjne wejść z pulpitu
|
||||||
static double fCalibrateOut[7][6]; // parametry kalibracyjne wyjść dla pulpitu
|
static double fCalibrateOut[7][6]; // parametry kalibracyjne wyjść dla pulpitu
|
||||||
static double fCalibrateOutMax[7]; // wartości maksymalne wyjść dla pulpitu
|
static double fCalibrateOutMax[7]; // wartości maksymalne wyjść dla pulpitu
|
||||||
|
|||||||
@@ -547,18 +547,18 @@ struct TMotorParameters
|
|||||||
|
|
||||||
struct TSecuritySystem
|
struct TSecuritySystem
|
||||||
{
|
{
|
||||||
int SystemType; /*0: brak, 1: czuwak aktywny, 2: SHP/sygnalizacja kabinowa*/
|
int SystemType { 0 }; /*0: brak, 1: czuwak aktywny, 2: SHP/sygnalizacja kabinowa*/
|
||||||
double AwareDelay; // czas powtarzania czuwaka
|
double AwareDelay { -1.0 }; // czas powtarzania czuwaka
|
||||||
double AwareMinSpeed; // minimalna prędkość załączenia czuwaka, normalnie 10% Vmax
|
double AwareMinSpeed; // minimalna prędkość załączenia czuwaka, normalnie 10% Vmax
|
||||||
double SoundSignalDelay;
|
double SoundSignalDelay { -1.0 };
|
||||||
double EmergencyBrakeDelay;
|
double EmergencyBrakeDelay { -1.0 };
|
||||||
int Status; /*0: wylaczony, 1: wlaczony, 2: czuwak, 4: shp, 8: alarm, 16: hamowanie awaryjne*/
|
int Status { 0 }; /*0: wylaczony, 1: wlaczony, 2: czuwak, 4: shp, 8: alarm, 16: hamowanie awaryjne*/
|
||||||
double SystemTimer;
|
double SystemTimer { 0.0 };
|
||||||
double SystemSoundCATimer;
|
double SystemSoundCATimer { 0.0 };
|
||||||
double SystemSoundSHPTimer;
|
double SystemSoundSHPTimer { 0.0 };
|
||||||
double SystemBrakeCATimer;
|
double SystemBrakeCATimer { 0.0 };
|
||||||
double SystemBrakeSHPTimer;
|
double SystemBrakeSHPTimer { 0.0 };
|
||||||
double SystemBrakeCATestTimer; // hunter-091012
|
double SystemBrakeCATestTimer { 0.0 }; // hunter-091012
|
||||||
int VelocityAllowed;
|
int VelocityAllowed;
|
||||||
int NextVelocityAllowed; /*predkosc pokazywana przez sygnalizacje kabinowa*/
|
int NextVelocityAllowed; /*predkosc pokazywana przez sygnalizacje kabinowa*/
|
||||||
bool RadioStop; // czy jest RadioStop
|
bool RadioStop; // czy jest RadioStop
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
int const null_handle = 0;
|
||||||
|
|
||||||
enum class resource_state {
|
enum class resource_state {
|
||||||
none,
|
none,
|
||||||
loading,
|
loading,
|
||||||
@@ -64,6 +66,11 @@ class ResourceManager
|
|||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using resource_timestamp = std::chrono::steady_clock::time_point;
|
||||||
|
|
||||||
|
// takes containers providing access to specific element through operator[]
|
||||||
|
// with elements of std::pair<resource *, resource_timestamp>
|
||||||
|
// the element should provide method release() freeing resources owned by the element
|
||||||
template <class Container_>
|
template <class Container_>
|
||||||
class garbage_collector {
|
class garbage_collector {
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef int texture_handle;
|
typedef int texture_handle;
|
||||||
int const null_handle = 0;
|
|
||||||
|
|
||||||
class texture_manager {
|
class texture_manager {
|
||||||
|
|
||||||
@@ -104,7 +103,7 @@ private:
|
|||||||
// types:
|
// types:
|
||||||
typedef std::pair<
|
typedef std::pair<
|
||||||
opengl_texture *,
|
opengl_texture *,
|
||||||
std::chrono::steady_clock::time_point > texturetimepoint_pair;
|
resource_timestamp > texturetimepoint_pair;
|
||||||
|
|
||||||
typedef std::vector< texturetimepoint_pair > texturetimepointpair_sequence;
|
typedef std::vector< texturetimepoint_pair > texturetimepointpair_sequence;
|
||||||
|
|
||||||
|
|||||||
66
Train.cpp
66
Train.cpp
@@ -4490,6 +4490,7 @@ bool TTrain::Update( double const Deltatime )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
btLampkaCzuwaka.Turn( false );
|
btLampkaCzuwaka.Turn( false );
|
||||||
|
|
||||||
btLampkaSHP.Turn(TestFlag(mvOccupied->SecuritySystem.Status, s_active));
|
btLampkaSHP.Turn(TestFlag(mvOccupied->SecuritySystem.Status, s_active));
|
||||||
}
|
}
|
||||||
else // wylaczone
|
else // wylaczone
|
||||||
@@ -5604,50 +5605,34 @@ TTrain::update_sounds( double const Deltatime ) {
|
|||||||
if( dsbSlipAlarm )
|
if( dsbSlipAlarm )
|
||||||
dsbSlipAlarm->Stop();
|
dsbSlipAlarm->Stop();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
// McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa
|
// McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa
|
||||||
if (mvOccupied->SecuritySystem.Status > 0)
|
if (mvOccupied->SecuritySystem.Status > 0)
|
||||||
{
|
{
|
||||||
// hunter-091012: rozdzielenie alarmow
|
// hunter-091012: rozdzielenie alarmow
|
||||||
if (TestFlag(mvOccupied->SecuritySystem.Status, s_CAalarm) ||
|
if( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm )
|
||||||
TestFlag(mvOccupied->SecuritySystem.Status, s_SHPalarm))
|
|| TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ) {
|
||||||
{
|
|
||||||
if (dsbBuzzer)
|
|
||||||
{
|
|
||||||
dsbBuzzer->GetStatus(&stat);
|
|
||||||
if (!(stat & DSBSTATUS_PLAYING))
|
|
||||||
{
|
|
||||||
play_sound( dsbBuzzer, DSBVOLUME_MAX, DSBPLAY_LOOPING );
|
|
||||||
Console::BitsSet(1 << 14); // ustawienie bitu 16 na PoKeys
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (dsbBuzzer)
|
|
||||||
{
|
|
||||||
dsbBuzzer->GetStatus(&stat);
|
|
||||||
if (stat & DSBSTATUS_PLAYING)
|
|
||||||
{
|
|
||||||
dsbBuzzer->Stop();
|
|
||||||
Console::BitsClear(1 << 14); // ustawienie bitu 16 na PoKeys
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // wylaczone
|
|
||||||
{
|
|
||||||
if (dsbBuzzer)
|
|
||||||
{
|
|
||||||
dsbBuzzer->GetStatus(&stat);
|
|
||||||
if (stat & DSBSTATUS_PLAYING)
|
|
||||||
{
|
|
||||||
dsbBuzzer->Stop();
|
|
||||||
Console::BitsClear(1 << 14); // ustawienie bitu 16 na PoKeys
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if( false == dsbBuzzer.is_playing() ) {
|
||||||
|
dsbBuzzer.play( sound_flags::looping );
|
||||||
|
Console::BitsSet( 1 << 14 ); // ustawienie bitu 16 na PoKeys
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if( true == dsbBuzzer.is_playing() ) {
|
||||||
|
dsbBuzzer.stop();
|
||||||
|
Console::BitsClear( 1 << 14 ); // ustawienie bitu 16 na PoKeys
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// wylaczone
|
||||||
|
if( true == dsbBuzzer.is_playing() ) {
|
||||||
|
dsbBuzzer.stop();
|
||||||
|
Console::BitsClear( 1 << 14 ); // ustawienie bitu 16 na PoKeys
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef EU07_USE_OLD_SOUNDCODE
|
||||||
/* if ((mvControlled->Mains) &&
|
/* if ((mvControlled->Mains) &&
|
||||||
(mvControlled->EngineType==ElectricSeriesMotor))
|
(mvControlled->EngineType==ElectricSeriesMotor))
|
||||||
{
|
{
|
||||||
@@ -5755,7 +5740,6 @@ bool TTrain::LoadMMediaFile(std::string const &asFileName)
|
|||||||
|
|
||||||
if (token == "internaldata:")
|
if (token == "internaldata:")
|
||||||
{
|
{
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
token = "";
|
token = "";
|
||||||
@@ -5964,7 +5948,7 @@ bool TTrain::LoadMMediaFile(std::string const &asFileName)
|
|||||||
rsFadeSound.FM = 1.0;
|
rsFadeSound.FM = 1.0;
|
||||||
rsFadeSound.FA = 1.0;
|
rsFadeSound.FA = 1.0;
|
||||||
*/
|
*/
|
||||||
rsFadeSound.deserialize( parser, sound_type::single, sound_parameters::amplitude | sound_parameters::frequency );
|
rsFadeSound.deserialize( parser, sound_type::single );
|
||||||
}
|
}
|
||||||
else if (token == "localbrakesound:")
|
else if (token == "localbrakesound:")
|
||||||
{
|
{
|
||||||
|
|||||||
2
Train.h
2
Train.h
@@ -453,7 +453,7 @@ private:
|
|||||||
float fCzuwakTestTimer; // hunter-091012: do testu czuwaka
|
float fCzuwakTestTimer; // hunter-091012: do testu czuwaka
|
||||||
float fLightsTimer; // yB 150617: timer do swiatel
|
float fLightsTimer; // yB 150617: timer do swiatel
|
||||||
|
|
||||||
int CAflag; // hunter-131211: dla osobnego zbijania CA i SHP
|
bool CAflag { false }; // hunter-131211: dla osobnego zbijania CA i SHP
|
||||||
|
|
||||||
double fPoslizgTimer;
|
double fPoslizgTimer;
|
||||||
TTrack *tor;
|
TTrack *tor;
|
||||||
|
|||||||
25
World.cpp
25
World.cpp
@@ -77,7 +77,7 @@ simulation_time::init() {
|
|||||||
m_time.wSecond = 0;
|
m_time.wSecond = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_yearday = yearday( m_time.wDay, m_time.wMonth, m_time.wYear );
|
m_yearday = year_day( m_time.wDay, m_time.wMonth, m_time.wYear );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -125,16 +125,15 @@ simulation_time::update( double const Deltatime ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
simulation_time::yearday( int Day, const int Month, const int Year ) {
|
simulation_time::year_day( int Day, const int Month, const int Year ) const {
|
||||||
|
|
||||||
char daytab[ 2 ][ 13 ] = {
|
char const daytab[ 2 ][ 13 ] = {
|
||||||
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
|
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
|
||||||
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||||||
};
|
};
|
||||||
int i, leap;
|
|
||||||
|
|
||||||
leap = ( Year % 4 == 0 ) && ( Year % 100 != 0 ) || ( Year % 400 == 0 );
|
int leap { ( Year % 4 == 0 ) && ( Year % 100 != 0 ) || ( Year % 400 == 0 ) };
|
||||||
for( i = 1; i < Month; ++i )
|
for( int i = 1; i < Month; ++i )
|
||||||
Day += daytab[ leap ][ i ];
|
Day += daytab[ leap ][ i ];
|
||||||
|
|
||||||
return Day;
|
return Day;
|
||||||
@@ -215,7 +214,6 @@ void TWorld::TrainDelete(TDynamicObject *d)
|
|||||||
Train = NULL;
|
Train = NULL;
|
||||||
Controlled = NULL; // tego też już nie ma
|
Controlled = NULL; // tego też już nie ma
|
||||||
mvControlled = NULL;
|
mvControlled = NULL;
|
||||||
Global::pUserDynamic = NULL; // tego też nie ma
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool TWorld::Init( GLFWwindow *Window ) {
|
bool TWorld::Init( GLFWwindow *Window ) {
|
||||||
@@ -267,7 +265,6 @@ bool TWorld::Init( GLFWwindow *Window ) {
|
|||||||
{
|
{
|
||||||
Controlled = Train->Dynamic();
|
Controlled = Train->Dynamic();
|
||||||
mvControlled = Controlled->ControlledFind()->MoverParameters;
|
mvControlled = Controlled->ControlledFind()->MoverParameters;
|
||||||
Global::pUserDynamic = Controlled; // renerowanie pojazdu względem kabiny
|
|
||||||
WriteLog("Player train init OK");
|
WriteLog("Player train init OK");
|
||||||
|
|
||||||
glfwSetWindowTitle( window, ( Global::AppName + " (" + Controlled->MoverParameters->Name + " @ " + Global::SceneryFile + ")" ).c_str() );
|
glfwSetWindowTitle( window, ( Global::AppName + " (" + Controlled->MoverParameters->Name + " @ " + Global::SceneryFile + ")" ).c_str() );
|
||||||
@@ -771,7 +768,6 @@ void TWorld::InOutKey( bool const Near )
|
|||||||
FreeFlyModeFlag = !FreeFlyModeFlag; // zmiana widoku
|
FreeFlyModeFlag = !FreeFlyModeFlag; // zmiana widoku
|
||||||
if (FreeFlyModeFlag) {
|
if (FreeFlyModeFlag) {
|
||||||
// jeżeli poza kabiną, przestawiamy w jej okolicę - OK
|
// jeżeli poza kabiną, przestawiamy w jej okolicę - OK
|
||||||
Global::pUserDynamic = NULL; // bez renderowania względem kamery
|
|
||||||
if (Train) {
|
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;
|
||||||
@@ -787,7 +783,6 @@ void TWorld::InOutKey( bool const Near )
|
|||||||
{ // jazda w kabinie
|
{ // jazda w kabinie
|
||||||
if (Train)
|
if (Train)
|
||||||
{
|
{
|
||||||
Global::pUserDynamic = Controlled; // renerowanie względem kamery
|
|
||||||
Train->Dynamic()->bDisplayCab = true;
|
Train->Dynamic()->bDisplayCab = true;
|
||||||
Train->Dynamic()->ABuSetModelShake(
|
Train->Dynamic()->ABuSetModelShake(
|
||||||
vector3(0, 0, 0)); // zerowanie przesunięcia przed powrotem?
|
vector3(0, 0, 0)); // zerowanie przesunięcia przed powrotem?
|
||||||
@@ -1061,6 +1056,8 @@ bool TWorld::Update() {
|
|||||||
Timer::subsystem.sim_total.stop();
|
Timer::subsystem.sim_total.stop();
|
||||||
|
|
||||||
simulation::Region->update_sounds();
|
simulation::Region->update_sounds();
|
||||||
|
audio::renderer.update( dt );
|
||||||
|
|
||||||
GfxRenderer.Update( dt );
|
GfxRenderer.Update( dt );
|
||||||
ResourceSweep();
|
ResourceSweep();
|
||||||
|
|
||||||
@@ -1136,12 +1133,10 @@ TWorld::Update_Camera( double const Deltatime ) {
|
|||||||
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 ) * Train->Dynamic()->VectorLeft() * Train->Dynamic()->MoverParameters->ActiveCab;
|
Camera.LookAt = Camera.Pos - ( lr ? -1 : 1 ) * Train->Dynamic()->VectorLeft() * Train->Dynamic()->MoverParameters->ActiveCab;
|
||||||
Global::SetCameraRotation( -modelrotate );
|
|
||||||
}
|
}
|
||||||
else { // patrzenie w kierunku osi pojazdu, z uwzględnieniem kabiny - jakby z lusterka,
|
else { // patrzenie w kierunku osi pojazdu, z uwzględnieniem kabiny - jakby z lusterka,
|
||||||
// ale bez odbicia
|
// ale bez odbicia
|
||||||
Camera.LookAt = Camera.Pos - Train->GetDirection() * Train->Dynamic()->MoverParameters->ActiveCab; //-1 albo 1
|
Camera.LookAt = Camera.Pos - Train->GetDirection() * Train->Dynamic()->MoverParameters->ActiveCab; //-1 albo 1
|
||||||
Global::SetCameraRotation( M_PI - modelrotate ); // tu już trzeba uwzględnić lusterka
|
|
||||||
}
|
}
|
||||||
Camera.Roll = std::atan( Train->pMechShake.x * Train->fMechRoll ); // hustanie kamery na boki
|
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
|
Camera.Pitch = 0.5 * std::atan( Train->vMechVelocity.z * Train->fMechPitch ); // hustanie kamery przod tyl
|
||||||
@@ -1174,11 +1169,10 @@ TWorld::Update_Camera( double const Deltatime ) {
|
|||||||
else // patrzenie w kierunku osi pojazdu, z uwzględnieniem kabiny
|
else // patrzenie w kierunku osi pojazdu, z uwzględnieniem kabiny
|
||||||
Camera.LookAt = Train->GetWorldMechPosition() + Train->GetDirection() * 5.0 * Train->Dynamic()->MoverParameters->ActiveCab; //-1 albo 1
|
Camera.LookAt = Train->GetWorldMechPosition() + Train->GetDirection() * 5.0 * Train->Dynamic()->MoverParameters->ActiveCab; //-1 albo 1
|
||||||
Camera.vUp = Train->GetUp();
|
Camera.vUp = Train->GetUp();
|
||||||
Global::SetCameraRotation( Camera.Yaw - modelrotate ); // tu już trzeba uwzględnić lusterka
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // kamera nieruchoma
|
else {
|
||||||
Global::SetCameraRotation( Camera.Yaw - M_PI );
|
// kamera nieruchoma
|
||||||
}
|
}
|
||||||
// all done, update camera position to the new value
|
// all done, update camera position to the new value
|
||||||
Global::pCameraPosition = Camera.Pos;
|
Global::pCameraPosition = Camera.Pos;
|
||||||
@@ -2118,7 +2112,6 @@ void TWorld::ChangeDynamic() {
|
|||||||
Train->Dynamic()->asBaseDir +
|
Train->Dynamic()->asBaseDir +
|
||||||
Train->Dynamic()->MoverParameters->TypeName + ".mmd" );
|
Train->Dynamic()->MoverParameters->TypeName + ".mmd" );
|
||||||
if( !FreeFlyModeFlag ) {
|
if( !FreeFlyModeFlag ) {
|
||||||
Global::pUserDynamic = Controlled; // renerowanie względem kamery
|
|
||||||
Train->Dynamic()->bDisplayCab = true;
|
Train->Dynamic()->bDisplayCab = true;
|
||||||
Train->Dynamic()->ABuSetModelShake(
|
Train->Dynamic()->ABuSetModelShake(
|
||||||
vector3( 0, 0, 0 ) ); // zerowanie przesunięcia przed powrotem?
|
vector3( 0, 0, 0 ) ); // zerowanie przesunięcia przed powrotem?
|
||||||
|
|||||||
7
World.h
7
World.h
@@ -39,13 +39,13 @@ public:
|
|||||||
second() const { return ( m_time.wMilliseconds * 0.001 + m_time.wSecond ); }
|
second() const { return ( m_time.wMilliseconds * 0.001 + m_time.wSecond ); }
|
||||||
int
|
int
|
||||||
year_day() const { return m_yearday; }
|
year_day() const { return m_yearday; }
|
||||||
|
// helper, calculates day of year from given date
|
||||||
|
int
|
||||||
|
year_day( int Day, int const Month, int const Year ) const;
|
||||||
int
|
int
|
||||||
julian_day() const;
|
julian_day() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// calculates day of year from given date
|
|
||||||
int
|
|
||||||
yearday( int Day, int const Month, int const Year );
|
|
||||||
// calculates day and month from given day of year
|
// calculates day and month from given day of year
|
||||||
void
|
void
|
||||||
daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Yearday );
|
daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Yearday );
|
||||||
@@ -115,7 +115,6 @@ TWorld();
|
|||||||
// calculates current season of the year based on set simulation date
|
// calculates current season of the year based on set simulation date
|
||||||
void compute_season( int const Yearday ) const;
|
void compute_season( int const Yearday ) const;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Update_Environment();
|
void Update_Environment();
|
||||||
void Update_Camera( const double Deltatime );
|
void Update_Camera( const double Deltatime );
|
||||||
|
|||||||
33
audio.cpp
33
audio.cpp
@@ -98,7 +98,7 @@ buffer_manager::~buffer_manager() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// creates buffer object out of data stored in specified file. returns: handle to the buffer or null_handle if creation failed
|
// creates buffer object out of data stored in specified file. returns: handle to the buffer or null_handle if creation failed
|
||||||
buffer_handle
|
audio::buffer_handle
|
||||||
buffer_manager::create( std::string const &Filename ) {
|
buffer_manager::create( std::string const &Filename ) {
|
||||||
|
|
||||||
auto filename { ToLower( Filename ) };
|
auto filename { ToLower( Filename ) };
|
||||||
@@ -114,14 +114,18 @@ buffer_manager::create( std::string const &Filename ) {
|
|||||||
std::begin( filename ), std::end( filename ),
|
std::begin( filename ), std::end( filename ),
|
||||||
'\\', '/' );
|
'\\', '/' );
|
||||||
|
|
||||||
// try dynamic-specific sounds first
|
audio::buffer_handle lookup { null_handle };
|
||||||
auto lookup { find_buffer( Global::asCurrentDynamicPath + filename ) };
|
std::string filelookup;
|
||||||
if( lookup != null_handle ) {
|
if( false == Global::asCurrentDynamicPath.empty() ) {
|
||||||
return lookup;
|
// try dynamic-specific sounds first
|
||||||
}
|
lookup = find_buffer( Global::asCurrentDynamicPath + filename );
|
||||||
std::string filelookup { find_file( Global::asCurrentDynamicPath + filename ) };
|
if( lookup != null_handle ) {
|
||||||
if( false == filelookup.empty() ) {
|
return lookup;
|
||||||
return emplace( filelookup );
|
}
|
||||||
|
filelookup = find_file( Global::asCurrentDynamicPath + filename );
|
||||||
|
if( false == filelookup.empty() ) {
|
||||||
|
return emplace( filelookup );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// if dynamic-specific lookup finds nothing, try the default sound folder
|
// if dynamic-specific lookup finds nothing, try the default sound folder
|
||||||
lookup = find_buffer( szSoundPath + filename );
|
lookup = find_buffer( szSoundPath + filename );
|
||||||
@@ -136,8 +140,15 @@ buffer_manager::create( std::string const &Filename ) {
|
|||||||
return null_handle;
|
return null_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// provides direct access to a specified buffer
|
||||||
|
audio::openal_buffer const &
|
||||||
|
buffer_manager::buffer( audio::buffer_handle const Buffer ) const {
|
||||||
|
|
||||||
|
return m_buffers[ Buffer ];
|
||||||
|
}
|
||||||
|
|
||||||
// places in the bank a buffer containing data stored in specified file. returns: handle to the buffer
|
// places in the bank a buffer containing data stored in specified file. returns: handle to the buffer
|
||||||
buffer_handle
|
audio::buffer_handle
|
||||||
buffer_manager::emplace( std::string Filename ) {
|
buffer_manager::emplace( std::string Filename ) {
|
||||||
|
|
||||||
buffer_handle const handle { m_buffers.size() };
|
buffer_handle const handle { m_buffers.size() };
|
||||||
@@ -151,7 +162,7 @@ buffer_manager::emplace( std::string Filename ) {
|
|||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_handle
|
audio::buffer_handle
|
||||||
buffer_manager::find_buffer( std::string const &Buffername ) const {
|
buffer_manager::find_buffer( std::string const &Buffername ) const {
|
||||||
|
|
||||||
auto lookup = m_buffermappings.find( Buffername );
|
auto lookup = m_buffermappings.find( Buffername );
|
||||||
|
|||||||
6
audio.h
6
audio.h
@@ -16,6 +16,7 @@ namespace audio {
|
|||||||
|
|
||||||
ALuint const null_resource { ~ALuint{ 0 } };
|
ALuint const null_resource { ~ALuint{ 0 } };
|
||||||
|
|
||||||
|
// wrapper for audio sample
|
||||||
struct openal_buffer {
|
struct openal_buffer {
|
||||||
// members
|
// members
|
||||||
ALuint id { null_resource }; // associated AL resource
|
ALuint id { null_resource }; // associated AL resource
|
||||||
@@ -36,6 +37,8 @@ private:
|
|||||||
|
|
||||||
using buffer_handle = std::size_t;
|
using buffer_handle = std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
class buffer_manager {
|
class buffer_manager {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -47,6 +50,9 @@ public:
|
|||||||
// creates buffer object out of data stored in specified file. returns: handle to the buffer or null_handle if creation failed
|
// creates buffer object out of data stored in specified file. returns: handle to the buffer or null_handle if creation failed
|
||||||
buffer_handle
|
buffer_handle
|
||||||
create( std::string const &Filename );
|
create( std::string const &Filename );
|
||||||
|
// provides direct access to a specified buffer
|
||||||
|
audio::openal_buffer const &
|
||||||
|
buffer( audio::buffer_handle const Buffer ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// types
|
// types
|
||||||
|
|||||||
@@ -10,12 +10,88 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
|
||||||
#include "audiorenderer.h"
|
#include "audiorenderer.h"
|
||||||
|
#include "sound.h"
|
||||||
#include "logs.h"
|
#include "logs.h"
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
|
|
||||||
openal_renderer renderer;
|
openal_renderer renderer;
|
||||||
|
|
||||||
|
// starts playback of queued buffers
|
||||||
|
void
|
||||||
|
openal_source::play() {
|
||||||
|
|
||||||
|
::alSourcePlay( id );
|
||||||
|
is_playing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stops the playback
|
||||||
|
void
|
||||||
|
openal_source::stop() {
|
||||||
|
|
||||||
|
::alSourcei( id, AL_LOOPING, AL_FALSE );
|
||||||
|
::alSourceStop( id );
|
||||||
|
// NOTE: we don't update the is_playing flag
|
||||||
|
// this way the state will change only on next update loop,
|
||||||
|
// giving the controller a chance to properly change state from cease to none
|
||||||
|
// even with multiple active sounds under control
|
||||||
|
}
|
||||||
|
|
||||||
|
// updates state of the source
|
||||||
|
void
|
||||||
|
openal_source::update( int const Deltatime ) {
|
||||||
|
|
||||||
|
// TODO: test whether the emitter was within range during the last tick, potentially update the counter and flag it for timeout
|
||||||
|
::alGetSourcei( id, AL_BUFFERS_PROCESSED, &buffer_index );
|
||||||
|
// for multipart sounds trim away processed sources until only one remains, the last one may be set to looping by the controller
|
||||||
|
ALuint bufferid;
|
||||||
|
while( ( buffer_index > 0 )
|
||||||
|
&& ( buffers.size() > 1 ) ) {
|
||||||
|
::alSourceUnqueueBuffers( id, 1, &bufferid );
|
||||||
|
buffers.erase( std::begin( buffers ) );
|
||||||
|
--buffer_index;
|
||||||
|
}
|
||||||
|
int state;
|
||||||
|
::alGetSourcei( id, AL_SOURCE_STATE, &state );
|
||||||
|
is_playing = ( state == AL_PLAYING );
|
||||||
|
// request instructions from the controller
|
||||||
|
controller->update( *this );
|
||||||
|
}
|
||||||
|
|
||||||
|
// toggles looping of the sound emitted by the source
|
||||||
|
void
|
||||||
|
openal_source::loop( bool const State ) {
|
||||||
|
|
||||||
|
::alSourcei(
|
||||||
|
id,
|
||||||
|
AL_LOOPING,
|
||||||
|
( State ?
|
||||||
|
AL_TRUE :
|
||||||
|
AL_FALSE ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// releases bound buffers and resets state of the class variables
|
||||||
|
// NOTE: doesn't release allocated implementation-side source
|
||||||
|
void
|
||||||
|
openal_source::clear() {
|
||||||
|
|
||||||
|
controller = nullptr;
|
||||||
|
// unqueue bound buffers:
|
||||||
|
// ensure no buffer is in use...
|
||||||
|
::alSourcei( id, AL_LOOPING, AL_FALSE );
|
||||||
|
::alSourceStop( id );
|
||||||
|
is_playing = false;
|
||||||
|
// ...prepare space for returned ids of unqueued buffers (not that we need that info)...
|
||||||
|
std::vector<ALuint> bufferids;
|
||||||
|
bufferids.resize( buffers.size() );
|
||||||
|
// ...release the buffers and update source data to match
|
||||||
|
::alSourceUnqueueBuffers( id, bufferids.size(), bufferids.data() );
|
||||||
|
buffers.clear();
|
||||||
|
buffer_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
openal_renderer::~openal_renderer() {
|
openal_renderer::~openal_renderer() {
|
||||||
|
|
||||||
::alcMakeContextCurrent( nullptr );
|
::alcMakeContextCurrent( nullptr );
|
||||||
@@ -24,12 +100,19 @@ openal_renderer::~openal_renderer() {
|
|||||||
if( m_device != nullptr ) { ::alcCloseDevice( m_device ); }
|
if( m_device != nullptr ) { ::alcCloseDevice( m_device ); }
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_handle
|
audio::buffer_handle
|
||||||
openal_renderer::fetch_buffer( std::string const &Filename ) {
|
openal_renderer::fetch_buffer( std::string const &Filename ) {
|
||||||
|
|
||||||
return m_buffers.create( Filename );
|
return m_buffers.create( Filename );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// provides direct access to a specified buffer
|
||||||
|
audio::openal_buffer const &
|
||||||
|
openal_renderer::buffer( audio::buffer_handle const Buffer ) const {
|
||||||
|
|
||||||
|
return m_buffers.buffer( Buffer );
|
||||||
|
}
|
||||||
|
|
||||||
// initializes the service
|
// initializes the service
|
||||||
bool
|
bool
|
||||||
openal_renderer::init() {
|
openal_renderer::init() {
|
||||||
@@ -42,11 +125,56 @@ openal_renderer::init() {
|
|||||||
// basic initialization failed
|
// basic initialization failed
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// all done
|
||||||
m_ready = true;
|
m_ready = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// schedules playback of specified sample, under control of the specified emitter
|
||||||
|
void
|
||||||
|
openal_renderer::insert( sound_source *Controller, audio::buffer_handle const Sound ) {
|
||||||
|
|
||||||
|
audio::openal_source::buffer_sequence buffers { Sound };
|
||||||
|
return
|
||||||
|
insert(
|
||||||
|
Controller,
|
||||||
|
std::begin( buffers ), std::end( buffers ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// updates state of all active emitters
|
||||||
|
void
|
||||||
|
openal_renderer::update( int const Deltatime ) {
|
||||||
|
|
||||||
|
auto source { std::begin( m_sources ) };
|
||||||
|
while( source != std::end( m_sources ) ) {
|
||||||
|
// update each source
|
||||||
|
source->update( Deltatime );
|
||||||
|
// if after the update the source isn't playing, put it away on the spare stack, it's done
|
||||||
|
if( false == source->is_playing ) {
|
||||||
|
source->clear();
|
||||||
|
m_sourcespares.push( *source );
|
||||||
|
source = m_sources.erase( source );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// otherwise proceed through the list normally
|
||||||
|
++source;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns an instance of implementation-side part of the sound emitter
|
||||||
|
audio::openal_source
|
||||||
|
openal_renderer::fetch_source() {
|
||||||
|
|
||||||
|
audio::openal_source soundsource;
|
||||||
|
if( false == m_sourcespares.empty() ) {
|
||||||
|
// reuse (a copy of) already allocated source
|
||||||
|
soundsource = m_sourcespares.top();
|
||||||
|
m_sourcespares.pop();
|
||||||
|
}
|
||||||
|
return soundsource;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
openal_renderer::init_caps() {
|
openal_renderer::init_caps() {
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,60 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
|
#include "resourcemanager.h"
|
||||||
|
|
||||||
|
class sound_source;
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
|
|
||||||
|
// implementation part of the sound emitter
|
||||||
|
// TODO: generic interface base, for implementations other than openAL
|
||||||
|
struct openal_source {
|
||||||
|
|
||||||
|
// types
|
||||||
|
using buffer_sequence = std::vector<audio::buffer_handle>;
|
||||||
|
|
||||||
|
// members
|
||||||
|
ALuint id { audio::null_resource }; // associated AL resource
|
||||||
|
sound_source *controller { nullptr }; // source controller
|
||||||
|
buffer_sequence buffers; // sequence of samples the source will emit
|
||||||
|
int buffer_index; // currently queued sample from the buffer sequence
|
||||||
|
bool is_playing { false };
|
||||||
|
|
||||||
|
// methods
|
||||||
|
template <class Iterator_>
|
||||||
|
openal_source &
|
||||||
|
bind( sound_source *Controller, Iterator_ First, Iterator_ Last ) {
|
||||||
|
controller = Controller;
|
||||||
|
buffers.insert( std::end( buffers ), First, Last );
|
||||||
|
if( id == audio::null_resource ) {
|
||||||
|
::alGenSources( 1, &id ); }
|
||||||
|
// look up and queue assigned buffers
|
||||||
|
std::vector<ALuint> bufferids;
|
||||||
|
for( auto const buffer : buffers ) {
|
||||||
|
bufferids.emplace_back( audio::renderer.buffer( buffer ).id ); }
|
||||||
|
::alSourceQueueBuffers( id, bufferids.size(), bufferids.data() );
|
||||||
|
return *this; }
|
||||||
|
// starts playback of queued buffers
|
||||||
|
void
|
||||||
|
play();
|
||||||
|
// stops the playback
|
||||||
|
void
|
||||||
|
stop();
|
||||||
|
// updates state of the source
|
||||||
|
void
|
||||||
|
update( int const Deltatime );
|
||||||
|
// toggles looping of the sound emitted by the source
|
||||||
|
void
|
||||||
|
loop( bool const State );
|
||||||
|
// releases bound buffers and resets state of the class variables
|
||||||
|
// NOTE: doesn't release allocated implementation-side source
|
||||||
|
void
|
||||||
|
clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class openal_renderer {
|
class openal_renderer {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -21,23 +72,46 @@ public:
|
|||||||
// methods
|
// methods
|
||||||
// buffer methods
|
// buffer methods
|
||||||
// returns handle to a buffer containing audio data from specified file
|
// returns handle to a buffer containing audio data from specified file
|
||||||
buffer_handle
|
audio::buffer_handle
|
||||||
fetch_buffer( std::string const &Filename );
|
fetch_buffer( std::string const &Filename );
|
||||||
|
// provides direct access to a specified buffer
|
||||||
|
audio::openal_buffer const &
|
||||||
|
buffer( audio::buffer_handle const Buffer ) const;
|
||||||
// core methods
|
// core methods
|
||||||
// initializes the service
|
// initializes the service
|
||||||
bool
|
bool
|
||||||
init();
|
init();
|
||||||
|
// schedules playback of provided range of samples, under control of the specified sound emitter
|
||||||
|
template <class Iterator_>
|
||||||
|
void
|
||||||
|
insert( sound_source *Controller, Iterator_ First, Iterator_ Last ) {
|
||||||
|
m_sources.emplace_back( fetch_source().bind( Controller, First, Last ) ); }
|
||||||
|
// schedules playback of specified sample, under control of the specified sound emitter
|
||||||
|
void
|
||||||
|
insert( sound_source *Controller, audio::buffer_handle const Sound );
|
||||||
|
// updates state of all active emitters
|
||||||
|
void
|
||||||
|
update( int const Deltatime );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// types
|
||||||
|
using source_list = std::list<audio::openal_source>;
|
||||||
|
using source_sequence = std::stack<audio::openal_source>;
|
||||||
// methods
|
// methods
|
||||||
bool
|
bool
|
||||||
init_caps();
|
init_caps();
|
||||||
|
// returns an instance of implementation-side part of the sound emitter
|
||||||
|
audio::openal_source
|
||||||
|
fetch_source();
|
||||||
// members
|
// members
|
||||||
ALCdevice * m_device { nullptr };
|
ALCdevice * m_device { nullptr };
|
||||||
ALCcontext * m_context { nullptr };
|
ALCcontext * m_context { nullptr };
|
||||||
bool m_ready { false }; // renderer is initialized and functional
|
bool m_ready { false }; // renderer is initialized and functional
|
||||||
|
|
||||||
buffer_manager m_buffers;
|
buffer_manager m_buffers;
|
||||||
|
// TBD: list of sources as vector, sorted by distance, for openal implementations with limited number of active sources?
|
||||||
|
source_list m_sources;
|
||||||
|
source_sequence m_sourcespares; // already created and currently unused sound sources
|
||||||
};
|
};
|
||||||
|
|
||||||
extern openal_renderer renderer;
|
extern openal_renderer renderer;
|
||||||
|
|||||||
@@ -225,15 +225,15 @@
|
|||||||
<ClCompile Include="messaging.cpp">
|
<ClCompile Include="messaging.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="sound.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="audiorenderer.cpp">
|
<ClCompile Include="audiorenderer.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="audio.cpp">
|
<ClCompile Include="audio.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="sound.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Globals.h">
|
<ClInclude Include="Globals.h">
|
||||||
@@ -449,13 +449,13 @@
|
|||||||
<ClInclude Include="messaging.h">
|
<ClInclude Include="messaging.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="audiorenderer.h">
|
<ClInclude Include="sound.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="audio.h">
|
<ClInclude Include="audio.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="sound.h">
|
<ClInclude Include="audiorenderer.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -395,7 +395,7 @@ geometrybank_manager::create_bank() {
|
|||||||
if( true == Global::bUseVBO ) { m_geometrybanks.emplace_back( std::make_shared<opengl_vbogeometrybank>(), std::chrono::steady_clock::time_point() ); }
|
if( true == Global::bUseVBO ) { m_geometrybanks.emplace_back( std::make_shared<opengl_vbogeometrybank>(), std::chrono::steady_clock::time_point() ); }
|
||||||
else { m_geometrybanks.emplace_back( std::make_shared<opengl_dlgeometrybank>(), std::chrono::steady_clock::time_point() ); }
|
else { m_geometrybanks.emplace_back( std::make_shared<opengl_dlgeometrybank>(), std::chrono::steady_clock::time_point() ); }
|
||||||
// NOTE: handle is effectively (index into chunk array + 1) this leaves value of 0 to serve as error/empty handle indication
|
// NOTE: handle is effectively (index into chunk array + 1) this leaves value of 0 to serve as error/empty handle indication
|
||||||
return { m_geometrybanks.size(), 0 };
|
return { static_cast<std::uint32_t>( m_geometrybanks.size() ), 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// creates a new geometry chunk of specified type from supplied vertex data, in specified bank. returns: handle to the chunk or NULL
|
// creates a new geometry chunk of specified type from supplied vertex data, in specified bank. returns: handle to the chunk or NULL
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ private:
|
|||||||
// types:
|
// types:
|
||||||
typedef std::pair<
|
typedef std::pair<
|
||||||
std::shared_ptr<geometry_bank>,
|
std::shared_ptr<geometry_bank>,
|
||||||
std::chrono::steady_clock::time_point > geometrybanktimepoint_pair;
|
resource_timestamp > geometrybanktimepoint_pair;
|
||||||
|
|
||||||
typedef std::deque< geometrybanktimepoint_pair > geometrybanktimepointpair_sequence;
|
typedef std::deque< geometrybanktimepoint_pair > geometrybanktimepointpair_sequence;
|
||||||
|
|
||||||
|
|||||||
@@ -696,9 +696,10 @@ opengl_renderer::setup_pass( renderpass_config &Config, rendermode const Mode, f
|
|||||||
point = lightviewmatrix * point;
|
point = lightviewmatrix * point;
|
||||||
}
|
}
|
||||||
bounding_box( frustumchunkmin, frustumchunkmax, std::begin( frustumchunkshapepoints ), std::end( frustumchunkshapepoints ) );
|
bounding_box( frustumchunkmin, frustumchunkmax, std::begin( frustumchunkshapepoints ), std::end( frustumchunkshapepoints ) );
|
||||||
// quantize the frustum points with 50 m resolution, to reduce shadow shimmer on scale/orientation changes
|
// quantize the frustum points and add some padding, to reduce shadow shimmer on scale changes
|
||||||
frustumchunkmin = 50.f * glm::floor( frustumchunkmin * ( 1.f / 50.f ) );
|
auto const quantizationstep{ std::min( Global::shadowtune.depth, 50.f ) };
|
||||||
frustumchunkmax = 50.f * glm::ceil( frustumchunkmax * ( 1.f / 50.f ) );
|
frustumchunkmin = quantizationstep * glm::floor( frustumchunkmin * ( 1.f / quantizationstep ) );
|
||||||
|
frustumchunkmax = quantizationstep * glm::ceil( frustumchunkmax * ( 1.f / quantizationstep ) );
|
||||||
// ...use the dimensions to set up light projection boundaries...
|
// ...use the dimensions to set up light projection boundaries...
|
||||||
// NOTE: since we only have one cascade map stage, we extend the chunk forward/back to catch areas normally covered by other stages
|
// NOTE: since we only have one cascade map stage, we extend the chunk forward/back to catch areas normally covered by other stages
|
||||||
camera.projection() *=
|
camera.projection() *=
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
#define EU07_USE_PICKING_FRAMEBUFFER
|
#define EU07_USE_PICKING_FRAMEBUFFER
|
||||||
//#define EU07_USE_DEBUG_SHADOWMAP
|
//#define EU07_USE_DEBUG_SHADOWMAP
|
||||||
#define EU07_USE_DEBUG_CAMERA
|
//#define EU07_USE_DEBUG_CAMERA
|
||||||
//#define EU07_USE_DEBUG_CULLING
|
//#define EU07_USE_DEBUG_CULLING
|
||||||
|
|
||||||
struct opengl_light {
|
struct opengl_light {
|
||||||
|
|||||||
@@ -460,10 +460,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
|
|||||||
|
|
||||||
auto *sound { deserialize_sound( Input, Scratchpad, nodedata ) };
|
auto *sound { deserialize_sound( Input, Scratchpad, nodedata ) };
|
||||||
if( false == simulation::Sounds.insert( sound ) ) {
|
if( false == simulation::Sounds.insert( sound ) ) {
|
||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
ErrorLog( "Bad scenario: sound node with duplicate name \"" + sound->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||||
ErrorLog( "Bad scenario: sound node with duplicate name \"" + sound->m_name + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
simulation::Region->insert_sound( sound, Scratchpad );
|
simulation::Region->insert_sound( sound, Scratchpad );
|
||||||
}
|
}
|
||||||
|
|||||||
140
sound.cpp
140
sound.cpp
@@ -10,6 +10,8 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
|
#include "parser.h"
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
// restores state of the class from provided data stream
|
// restores state of the class from provided data stream
|
||||||
sound_source &
|
sound_source &
|
||||||
@@ -25,12 +27,14 @@ sound_source::deserialize( cParser &Input, sound_type const Legacytype, int cons
|
|||||||
switch( Legacytype ) {
|
switch( Legacytype ) {
|
||||||
case sound_type::single: {
|
case sound_type::single: {
|
||||||
// single sample only
|
// single sample only
|
||||||
Input.getTokens( 1, true, "\n\r\t ,;" );
|
m_soundmain = audio::renderer.fetch_buffer( Input.getToken<std::string>( true, "\n\r\t ,;" ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case sound_type::multipart: {
|
case sound_type::multipart: {
|
||||||
// three samples: start, middle, stop
|
// three samples: start, middle, stop
|
||||||
Input.getTokens( 3, true, "\n\r\t ,;" );
|
m_soundbegin = audio::renderer.fetch_buffer( Input.getToken<std::string>( true, "\n\r\t ,;" ) );
|
||||||
|
m_soundmain = audio::renderer.fetch_buffer( Input.getToken<std::string>( true, "\n\r\t ,;" ) );
|
||||||
|
m_soundend = audio::renderer.fetch_buffer( Input.getToken<std::string>( true, "\n\r\t ,;" ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@@ -53,14 +57,142 @@ sound_source::deserialize( cParser &Input, sound_type const Legacytype, int cons
|
|||||||
|
|
||||||
// issues contextual play commands for the audio renderer
|
// issues contextual play commands for the audio renderer
|
||||||
void
|
void
|
||||||
sound_source::play() {
|
sound_source::play( int const Flags ) {
|
||||||
|
|
||||||
|
if( ( false == Global::bSoundEnabled )
|
||||||
|
|| ( true == empty() ) ) {
|
||||||
|
// if the sound is disabled altogether or nothing can be emitted from this source, no point wasting time
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_flags = Flags;
|
||||||
|
|
||||||
|
switch( m_stage ) {
|
||||||
|
case stage::none:
|
||||||
|
case stage::restart: {
|
||||||
|
if( m_soundbegin != null_handle ) {
|
||||||
|
std::vector<audio::buffer_handle> bufferlist{ m_soundbegin, m_soundmain };
|
||||||
|
audio::renderer.insert( this, std::begin( bufferlist ), std::end( bufferlist ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
audio::renderer.insert( this, m_soundmain );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case stage::main: {
|
||||||
|
// TODO: schedule another main sample playback, or a suitable sample from the table for combined sources
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case stage::end: {
|
||||||
|
// schedule stop of current sequence end sample...
|
||||||
|
m_stage = stage::restart;
|
||||||
|
// ... and queue startup or main sound again
|
||||||
|
return play( Flags );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stops currently active play commands controlled by this emitter
|
||||||
|
void
|
||||||
|
sound_source::stop() {
|
||||||
|
|
||||||
|
if( ( m_stage == stage::none )
|
||||||
|
|| ( m_stage == stage::end ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( m_stage ) {
|
||||||
|
case stage::begin:
|
||||||
|
case stage::main: {
|
||||||
|
// set the source to kill any currently active sounds
|
||||||
|
m_stage = stage::cease;
|
||||||
|
if( m_soundend != null_handle ) {
|
||||||
|
// and if there's defined sample for the sound end, play it instead
|
||||||
|
audio::renderer.insert( this, m_soundend );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case stage::end: {
|
||||||
|
// set the source to kill any currently active sounds
|
||||||
|
m_stage = stage::cease;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// adjusts parameters of provided implementation-side sound source
|
||||||
|
void
|
||||||
|
sound_source::update( audio::openal_source &Source ) {
|
||||||
|
|
||||||
|
if( true == Source.is_playing ) {
|
||||||
|
|
||||||
|
// kill the sound if requested
|
||||||
|
if( m_stage == stage::cease ) {
|
||||||
|
Source.stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: positional update
|
||||||
|
if( m_soundbegin != null_handle ) {
|
||||||
|
// multipart sound
|
||||||
|
// detect the moment when the sound moves from startup sample to the main
|
||||||
|
if( ( m_stage == stage::begin )
|
||||||
|
&& ( Source.buffers[ Source.buffer_index ] == m_soundmain ) ) {
|
||||||
|
// when it happens update active sample flags, and activate the looping
|
||||||
|
Source.loop( true );
|
||||||
|
m_stage = stage::main;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// if the emitter isn't playing it's either done or wasn't yet started
|
||||||
|
// we can determine this from number of processed buffers
|
||||||
|
if( Source.buffer_index != Source.buffers.size() ) {
|
||||||
|
auto const buffer { Source.buffers[ Source.buffer_index ] };
|
||||||
|
if( buffer == m_soundbegin ) { m_stage = stage::begin; }
|
||||||
|
// TODO: take ito accound sample table for combined sounds
|
||||||
|
else if( buffer == m_soundmain ) { m_stage = stage::main; }
|
||||||
|
else if( buffer == m_soundend ) { m_stage = stage::end; }
|
||||||
|
// TODO: emitter initialization
|
||||||
|
if( ( buffer == m_soundmain )
|
||||||
|
&& ( true == TestFlag( m_flags, sound_flags::looping ) ) ) {
|
||||||
|
// main sample can be optionally set to loop
|
||||||
|
Source.loop( true );
|
||||||
|
}
|
||||||
|
// all set, start playback
|
||||||
|
Source.play();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//
|
||||||
|
auto const buffer { Source.buffers[ Source.buffer_index - 1 ] };
|
||||||
|
if( ( buffer == m_soundend )
|
||||||
|
|| ( ( m_soundend == null_handle )
|
||||||
|
&& ( buffer == m_soundmain ) ) ) {
|
||||||
|
m_stage = stage::none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
sound_source::empty() const {
|
sound_source::empty() const {
|
||||||
|
|
||||||
return true;
|
// NOTE: we test only the main sound, won't bother playing potential bookends if this is missing
|
||||||
|
// TODO: take into account presence of sample table, for combined sounds
|
||||||
|
return ( m_soundmain == null_handle );
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns true if the source is emitting any sound
|
||||||
|
bool
|
||||||
|
sound_source::is_playing() const {
|
||||||
|
|
||||||
|
return ( m_stage != stage::none );
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
48
sound.h
48
sound.h
@@ -10,7 +10,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "audiorenderer.h"
|
#include "audiorenderer.h"
|
||||||
#include "parser.h"
|
#include "classes.h"
|
||||||
#include "names.h"
|
#include "names.h"
|
||||||
|
|
||||||
enum sound_type {
|
enum sound_type {
|
||||||
@@ -19,14 +19,18 @@ enum sound_type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum sound_parameters {
|
enum sound_parameters {
|
||||||
none,
|
range = 0x1,
|
||||||
range = 0x1,
|
|
||||||
amplitude = 0x2,
|
amplitude = 0x2,
|
||||||
frequency = 0x4
|
frequency = 0x4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum sound_flags {
|
||||||
|
looping = 0x1, // the main sample will be looping; implied for multi-sounds
|
||||||
|
exclusive = 0x2 // the source won't dispatch more than one active instance of the sound; implied for multi-sounds
|
||||||
|
};
|
||||||
|
|
||||||
// mini controller and audio dispatcher; issues play commands for the audio renderer,
|
// mini controller and audio dispatcher; issues play commands for the audio renderer,
|
||||||
// updates parameters of assigned audio sources for the playback duration
|
// updates parameters of created audio emitters for the playback duration
|
||||||
// TODO: move to simulation namespace after clean up of owner classes
|
// TODO: move to simulation namespace after clean up of owner classes
|
||||||
class sound_source {
|
class sound_source {
|
||||||
|
|
||||||
@@ -34,15 +38,18 @@ public:
|
|||||||
// methods
|
// methods
|
||||||
// restores state of the class from provided data stream
|
// restores state of the class from provided data stream
|
||||||
sound_source &
|
sound_source &
|
||||||
deserialize( cParser &Input, sound_type const Legacytype, int const Legacyparameters = sound_parameters::none );
|
deserialize( cParser &Input, sound_type const Legacytype, int const Legacyparameters = NULL );
|
||||||
sound_source &
|
sound_source &
|
||||||
deserialize( std::string const &Input, sound_type const Legacytype, int const Legacyparameters = sound_parameters::none );
|
deserialize( std::string const &Input, sound_type const Legacytype, int const Legacyparameters = NULL );
|
||||||
// issues contextual play commands for the audio renderer
|
// issues contextual play commands for the audio renderer
|
||||||
void
|
void
|
||||||
play();
|
play( int const Flags = NULL );
|
||||||
// sets volume of audio streams associated with this source
|
// stops currently active play commands controlled by this emitter
|
||||||
sound_source &
|
void
|
||||||
volume( float const Volume );
|
stop();
|
||||||
|
// adjusts parameters of provided implementation-side sound source
|
||||||
|
void
|
||||||
|
update( audio::openal_source &Source );
|
||||||
// sound source name setter/getter
|
// sound source name setter/getter
|
||||||
void
|
void
|
||||||
name( std::string Name );
|
name( std::string Name );
|
||||||
@@ -51,10 +58,31 @@ public:
|
|||||||
// returns true if there isn't any sound buffer associated with the object, false otherwise
|
// returns true if there isn't any sound buffer associated with the object, false otherwise
|
||||||
bool
|
bool
|
||||||
empty() const;
|
empty() const;
|
||||||
|
// returns true if the source is emitting any sound
|
||||||
|
bool
|
||||||
|
is_playing() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// types
|
||||||
|
enum stage {
|
||||||
|
none,
|
||||||
|
begin,
|
||||||
|
main,
|
||||||
|
end,
|
||||||
|
cease,
|
||||||
|
restart
|
||||||
|
};
|
||||||
|
|
||||||
// members
|
// members
|
||||||
|
TDynamicObject * m_owner { nullptr }; // optional, the vehicle carrying this sound source
|
||||||
|
glm::vec3 m_offset; // relative position of the source, either from the owner or the region centre
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
|
stage m_stage{ stage::none };
|
||||||
|
int m_flags{ NULL };
|
||||||
|
audio::buffer_handle m_soundmain { null_handle }; // main sound emitted by the source
|
||||||
|
audio::buffer_handle m_soundbegin { null_handle }; // optional, sound emitted before the main sound
|
||||||
|
audio::buffer_handle m_soundend { null_handle }; // optional, sound emitted after the main sound
|
||||||
|
// TODO: table of samples with associated values, activated when controlling variable matches the value
|
||||||
};
|
};
|
||||||
|
|
||||||
// sound source name setter/getter
|
// sound source name setter/getter
|
||||||
|
|||||||
25
sun.cpp
25
sun.cpp
@@ -14,10 +14,6 @@ cSun::cSun() {
|
|||||||
setLocation( 19.00f, 52.00f ); // default location roughly in centre of Poland
|
setLocation( 19.00f, 52.00f ); // default location roughly in centre of Poland
|
||||||
m_observer.press = 1013.0; // surface pressure, millibars
|
m_observer.press = 1013.0; // surface pressure, millibars
|
||||||
m_observer.temp = 15.0; // ambient dry-bulb temperature, degrees C
|
m_observer.temp = 15.0; // ambient dry-bulb temperature, degrees C
|
||||||
|
|
||||||
TIME_ZONE_INFORMATION timezoneinfo; // TODO: timezone dependant on geographic location
|
|
||||||
::GetTimeZoneInformation( &timezoneinfo );
|
|
||||||
m_observer.timezone = -timezoneinfo.Bias / 60.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cSun::~cSun() { gluDeleteQuadric( sunsphere ); }
|
cSun::~cSun() { gluDeleteQuadric( sunsphere ); }
|
||||||
@@ -27,6 +23,27 @@ cSun::init() {
|
|||||||
|
|
||||||
sunsphere = gluNewQuadric();
|
sunsphere = gluNewQuadric();
|
||||||
gluQuadricNormals( sunsphere, GLU_SMOOTH );
|
gluQuadricNormals( sunsphere, GLU_SMOOTH );
|
||||||
|
|
||||||
|
// calculate and set timezone for the current date of the simulation
|
||||||
|
// TODO: timezone dependant on geographic location
|
||||||
|
TIME_ZONE_INFORMATION timezoneinfo;
|
||||||
|
::GetTimeZoneInformation( &timezoneinfo );
|
||||||
|
// account for potential daylight/normal time bias
|
||||||
|
// NOTE: we're using xp-compatible time zone information and current year, instead of 'historically proper' values
|
||||||
|
auto zonebias { timezoneinfo.Bias };
|
||||||
|
auto const year { simulation::Time.data().wYear };
|
||||||
|
auto const yearday { simulation::Time.year_day() };
|
||||||
|
if( yearday < simulation::Time.year_day( timezoneinfo.DaylightDate.wDay, timezoneinfo.DaylightDate.wMonth, year ) ) {
|
||||||
|
zonebias += timezoneinfo.StandardBias;
|
||||||
|
}
|
||||||
|
else if( yearday < simulation::Time.year_day( timezoneinfo.StandardDate.wDay, timezoneinfo.StandardDate.wMonth, year ) ) {
|
||||||
|
zonebias += timezoneinfo.DaylightBias;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
zonebias += timezoneinfo.StandardBias;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_observer.timezone = -zonebias / 60.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
Reference in New Issue
Block a user