mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
dynamically assigned render lights
This commit is contained in:
@@ -3760,12 +3760,14 @@ void TDynamicObject::Render()
|
||||
// double ObjDist= SquareMagnitude(Global::pCameraPosition-pos);
|
||||
if (this == Global::pUserDynamic)
|
||||
{ // specjalne ustawienie, aby nie trzęsło
|
||||
#ifdef EU07_USE_OLD_LIGHTING_MODEL
|
||||
if (Global::bSmudge)
|
||||
{ // jak jest widoczna smuga, to pojazd renderować po
|
||||
// wyrenderowaniu smugi
|
||||
glPopMatrix(); // a to trzeba zebrać przed wyjściem
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// if (Global::pWorld->) //tu trzeba by ustawić animacje na modelu
|
||||
// zewnętrznym
|
||||
glLoadIdentity(); // zacząć od macierzy jedynkowej
|
||||
|
||||
6
DynObj.h
6
DynObj.h
@@ -420,7 +420,7 @@ public: // modele składowe pojazdu
|
||||
void Render();
|
||||
void RenderAlpha();
|
||||
void RenderSounds();
|
||||
inline vector3 GetPosition()
|
||||
inline vector3 GetPosition() const
|
||||
{
|
||||
return vPosition;
|
||||
};
|
||||
@@ -436,7 +436,7 @@ public: // modele składowe pojazdu
|
||||
{
|
||||
return iAxleFirst ? Axle1.pPosition : Axle0.pPosition;
|
||||
};
|
||||
inline vector3 VectorFront()
|
||||
inline vector3 VectorFront() const
|
||||
{
|
||||
return vFront;
|
||||
};
|
||||
@@ -456,7 +456,7 @@ public: // modele składowe pojazdu
|
||||
{
|
||||
return MoverParameters->Vel;
|
||||
};
|
||||
inline double GetLength()
|
||||
inline double GetLength() const
|
||||
{
|
||||
return MoverParameters->Dim.L;
|
||||
};
|
||||
|
||||
3
EU07.cpp
3
EU07.cpp
@@ -718,6 +718,9 @@ int WINAPI WinMain(HINSTANCE hInstance, // instance
|
||||
fullscreen))
|
||||
return 0; // quit if window was not created
|
||||
SetForegroundWindow(hWnd);
|
||||
|
||||
GfxRenderer.Init();
|
||||
|
||||
// McZapkie: proba przeplukania klawiatury
|
||||
Console *pConsole = new Console(); // Ra: nie wiem, czy ma to sens, ale jakoś zainicjowac trzeba
|
||||
while (Console::Pressed(VK_F10))
|
||||
|
||||
12
Globals.cpp
12
Globals.cpp
@@ -104,8 +104,7 @@ GLfloat Global::diffuseLight[] = {0.85f, 0.85f, 0.80f, 1.0f};
|
||||
GLfloat Global::specularLight[] = {0.95f, 0.94f, 0.90f, 1.0f};
|
||||
#else
|
||||
opengl_light Global::DayLight;
|
||||
opengl_light Global::VehicleLight;
|
||||
opengl_light Global::VehicleLightRear;
|
||||
int Global::DynamicLightCount{ 3 };
|
||||
#endif
|
||||
GLfloat Global::whiteLight[] = {1.00f, 1.00f, 1.00f, 1.0f};
|
||||
GLfloat Global::noLight[] = {0.00f, 0.00f, 0.00f, 1.0f};
|
||||
@@ -577,7 +576,14 @@ void Global::ConfigParse(cParser &Parser)
|
||||
std::tm *localtime = std::localtime(&timenow);
|
||||
Global::fMoveLight = localtime->tm_yday + 1; // numer bieżącego dnia w roku
|
||||
}
|
||||
// TODO: calculate lights single time here for static setup. or get rid of static setup
|
||||
}
|
||||
else if( token == "dynamiclights" ) {
|
||||
// number of dynamic lights in the scene
|
||||
Parser.getTokens( 1, false );
|
||||
Parser >> Global::DynamicLightCount;
|
||||
// clamp the light number
|
||||
Global::DynamicLightCount = std::min( 7, Global::DynamicLightCount ); // max 8 lights per opengl specs, and one used for sun
|
||||
Global::DynamicLightCount = std::max( 1, Global::DynamicLightCount ); // at least one light for controlled vehicle
|
||||
}
|
||||
else if (token == "smoothtraction")
|
||||
{
|
||||
|
||||
@@ -233,9 +233,7 @@ class Global
|
||||
#else
|
||||
// TODO: put these things in the renderer
|
||||
static opengl_light DayLight;
|
||||
// TODO: possibly create a pool of few lights which can be attached to nearby vehicles
|
||||
static opengl_light VehicleLight;
|
||||
static opengl_light VehicleLightRear;
|
||||
static int DynamicLightCount;
|
||||
#endif
|
||||
static GLfloat whiteLight[];
|
||||
static GLfloat noLight[];
|
||||
|
||||
101
Ground.cpp
101
Ground.cpp
@@ -1841,29 +1841,20 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
case TP_DYNAMIC:
|
||||
tmp->DynamicObject = new TDynamicObject();
|
||||
// tmp->DynamicObject->Load(Parser);
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
str1 = token; // katalog
|
||||
// McZapkie: doszedl parametr ze zmienialna skora
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
Skin = token; // tekstura wymienna
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
str3 = token; // McZapkie-131102: model w MMD
|
||||
parser->getTokens(3);
|
||||
*parser
|
||||
>> str1 // katalog
|
||||
>> Skin // tekstura wymienna
|
||||
>> str3; // McZapkie-131102: model w MMD
|
||||
if (bTrainSet)
|
||||
{ // jeśli pojazd jest umieszczony w składzie
|
||||
str = asTrainSetTrack;
|
||||
parser->getTokens();
|
||||
*parser >> tf1; // Ra: -1 oznacza odwrotne wstawienie, normalnie w składzie 0
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
DriverType = token; // McZapkie:010303 - w przyszlosci rozne
|
||||
// konfiguracje mechanik/pomocnik itp
|
||||
parser->getTokens(3);
|
||||
*parser
|
||||
>> tf1 // Ra: -1 oznacza odwrotne wstawienie, normalnie w składzie 0
|
||||
>> DriverType // McZapkie:010303 - w przyszlosci rozne konfiguracje mechanik/pomocnik itp
|
||||
>> str4;
|
||||
tf3 = fTrainSetVel; // prędkość
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
str4 = token;
|
||||
int2 = str4.find("."); // yB: wykorzystuje tutaj zmienna, ktora potem bedzie ladunkiem
|
||||
if (int2 != string::npos) // yB: jesli znalazl kropke, to ja przetwarza jako parametry
|
||||
{
|
||||
@@ -1892,17 +1883,12 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
fTrainSetDist = 0; // zerowanie dodatkowego przesunięcia
|
||||
asTrainName = ""; // puste oznacza jazdę pojedynczego bez rozkładu, "none" jest dla
|
||||
// składu (trainset)
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
str = token; // track
|
||||
parser->getTokens();
|
||||
*parser >> tf1; // Ra: -1 oznacza odwrotne wstawienie
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
DriverType = token; // McZapkie:010303: obsada
|
||||
parser->getTokens();
|
||||
*parser >>
|
||||
tf3; // prędkość, niektórzy wpisują tu "3" jako sprzęg, żeby nie było tabliczki
|
||||
parser->getTokens(4);
|
||||
*parser
|
||||
>> str // track
|
||||
>> tf1 // Ra: -1 oznacza odwrotne wstawienie
|
||||
>> DriverType // McZapkie:010303: obsada
|
||||
>> tf3; // prędkość, niektórzy wpisują tu "3" jako sprzęg, żeby nie było tabliczki
|
||||
iTrainSetWehicleNumber = 0;
|
||||
TempConnectionType[iTrainSetWehicleNumber] = 3; // likwidacja tabliczki na końcu?
|
||||
}
|
||||
@@ -1911,8 +1897,7 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
if (int2 > 0)
|
||||
{ // jeżeli ładunku jest więcej niż 0, to rozpoznajemy jego typ
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
str2 = token; // LoadType
|
||||
*parser >> str2; // LoadType
|
||||
if (str2 == "enddynamic") // idiotoodporność: ładunek bez podanego typu
|
||||
{
|
||||
str2 = "";
|
||||
@@ -1986,6 +1971,16 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
}
|
||||
if (token.compare("enddynamic") != 0)
|
||||
Error("enddynamic statement missing");
|
||||
/*
|
||||
if( tmp->DynamicObject->MoverParameters->LightPowerSource.SourceType != TPowerSource::NotDefined ) {
|
||||
// if the vehicle has defined light source, it can (potentially) emit light, so add it to the light array
|
||||
*/
|
||||
if( tmp->DynamicObject->MoverParameters->SecuritySystem.SystemType != 0 ) {
|
||||
// we check for presence of security system, as a way to determine whether the vehicle is a controllable engine
|
||||
// NOTE: this isn't 100% precise, e.g. middle EZT module comes with security system, while it has no lights
|
||||
m_lights.insert( tmp->DynamicObject );
|
||||
}
|
||||
|
||||
break;
|
||||
case TP_MODEL:
|
||||
if (rmin < 0)
|
||||
@@ -4558,6 +4553,25 @@ bool TGround::Update(double dt, int iter)
|
||||
return true;
|
||||
};
|
||||
|
||||
// updates scene lights array
|
||||
void
|
||||
TGround::Update_Lights() {
|
||||
|
||||
m_lights.update();
|
||||
// arrange the light array from closest to farthest from current position of the camera
|
||||
auto const camera = Global::pCameraPosition;
|
||||
std::sort(
|
||||
m_lights.data.begin(),
|
||||
m_lights.data.end(),
|
||||
[&]( light_array::light_record const &Left, light_array::light_record const &Right ) {
|
||||
// move lights which are off at the end...
|
||||
if( Left.intensity == 0.0f ) { return false; }
|
||||
if( Right.intensity == 0.0f ) { return true; }
|
||||
// ...otherwise prefer closer and/or brigher light sources
|
||||
return ((camera - Left.position).LengthSquared() * (1.0f - Left.intensity)) < ((camera - Right.position).LengthSquared() * (1.0f - Right.intensity));
|
||||
} );
|
||||
}
|
||||
|
||||
// Winger 170204 - szukanie trakcji nad pantografami
|
||||
bool TGround::GetTraction(TDynamicObject *model)
|
||||
{ // aktualizacja drutu zasilającego dla każdego pantografu, żeby odczytać napięcie
|
||||
@@ -4808,6 +4822,27 @@ bool TGround::GetTraction(TDynamicObject *model)
|
||||
return true;
|
||||
};
|
||||
|
||||
bool
|
||||
TGround::Render( Math3D::vector3 const &Camera ) {
|
||||
|
||||
GfxRenderer.Update_Lights( m_lights );
|
||||
|
||||
if( Global::bUseVBO ) { // renderowanie przez VBO
|
||||
if( !RenderVBO( Camera ) )
|
||||
return false;
|
||||
if( !RenderAlphaVBO( Camera ) )
|
||||
return false;
|
||||
}
|
||||
else { // renderowanie przez Display List
|
||||
if( !RenderDL( Camera ) )
|
||||
return false;
|
||||
if( !RenderAlphaDL( Camera ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TGround::RenderDL(vector3 pPosition)
|
||||
{ // renderowanie scenerii z Display List - faza nieprzezroczystych
|
||||
glDisable(GL_BLEND);
|
||||
@@ -5339,6 +5374,8 @@ void TGround::DynamicRemove(TDynamicObject *dyn)
|
||||
node = (*n); // zapamiętanie węzła, aby go usunąć
|
||||
(*n) = node->nNext; // pominięcie na liście
|
||||
Global::TrainDelete(d);
|
||||
// remove potential entries in the light array
|
||||
m_lights.remove( d );
|
||||
d = d->Next(); // przejście do kolejnego pojazdu, póki jeszcze jest
|
||||
delete node; // usuwanie fizyczne z pamięci
|
||||
}
|
||||
|
||||
8
Ground.h
8
Ground.h
@@ -16,7 +16,9 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "ResourceManager.h"
|
||||
#include "Texture.h"
|
||||
#include "dumb3d.h"
|
||||
#include "Float3d.h"
|
||||
#include "Names.h"
|
||||
#include "lightarray.h"
|
||||
|
||||
using namespace Math3D;
|
||||
|
||||
@@ -303,11 +305,11 @@ class TGround
|
||||
TNames *sTracks = nullptr; // posortowane nazwy torów i eventów
|
||||
#else
|
||||
typedef std::unordered_map<std::string, TEvent *> event_map;
|
||||
// typedef std::unordered_map<std::string, TGroundNode *> groundnode_map;
|
||||
event_map m_eventmap;
|
||||
// groundnode_map m_memcellmap, m_modelmap, m_trackmap;
|
||||
TNames<TGroundNode *> m_trackmap;
|
||||
#endif
|
||||
light_array m_lights; // collection of dynamic light sources present in the scene
|
||||
|
||||
private: // metody prywatne
|
||||
bool EventConditon(TEvent *e);
|
||||
|
||||
@@ -350,8 +352,10 @@ class TGround
|
||||
void MoveGroundNode(vector3 pPosition);
|
||||
void UpdatePhys(double dt, int iter); // aktualizacja fizyki stałym krokiem
|
||||
bool Update(double dt, int iter); // aktualizacja przesunięć zgodna z FPS
|
||||
void Update_Lights(); // updates scene lights array
|
||||
bool AddToQuery(TEvent *Event, TDynamicObject *Node);
|
||||
bool GetTraction(TDynamicObject *model);
|
||||
bool Render( Math3D::vector3 const &Camera );
|
||||
bool RenderDL(vector3 pPosition);
|
||||
bool RenderAlphaDL(vector3 pPosition);
|
||||
bool RenderVBO(vector3 pPosition);
|
||||
|
||||
110
World.cpp
110
World.cpp
@@ -512,25 +512,6 @@ bool TWorld::Init(HWND NhWnd, HDC hDC)
|
||||
Global::DayLight.diffuse[ 0 ] = 255.0 / 255.0;
|
||||
Global::DayLight.diffuse[ 1 ] = 242.0 / 255.0;
|
||||
Global::DayLight.diffuse[ 2 ] = 231.0 / 255.0;
|
||||
|
||||
Global::VehicleLight.id = opengl_renderer::vehiclelight;
|
||||
// directional light
|
||||
Global::VehicleLight.position[ 3 ] = 1.0f;
|
||||
::glLightf( opengl_renderer::vehiclelight, GL_SPOT_CUTOFF, 20.0f );
|
||||
::glLightf( opengl_renderer::vehiclelight, GL_SPOT_EXPONENT, 10.0f );
|
||||
::glLightf( opengl_renderer::vehiclelight, GL_CONSTANT_ATTENUATION, 0.0f );
|
||||
::glLightf( opengl_renderer::vehiclelight, GL_LINEAR_ATTENUATION, 0.035f );
|
||||
// halogen light. TODO: allow light type definition
|
||||
Global::VehicleLight.diffuse[ 0 ] = 255.0 / 255.0;
|
||||
Global::VehicleLight.diffuse[ 1 ] = 241.0 / 255.0;
|
||||
Global::VehicleLight.diffuse[ 2 ] = 224.0 / 255.0;
|
||||
// rear light
|
||||
Global::VehicleLightRear = Global::VehicleLight;
|
||||
Global::VehicleLightRear.id = opengl_renderer::vehiclelightrear;
|
||||
::glLightf( opengl_renderer::vehiclelightrear, GL_SPOT_CUTOFF, 20.0f );
|
||||
::glLightf( opengl_renderer::vehiclelightrear, GL_SPOT_EXPONENT, 10.0f );
|
||||
::glLightf( opengl_renderer::vehiclelightrear, GL_CONSTANT_ATTENUATION, 0.0f );
|
||||
::glLightf( opengl_renderer::vehiclelightrear, GL_LINEAR_ATTENUATION, 0.035f );
|
||||
#endif
|
||||
|
||||
Ground.Init(Global::SceneryFile, hDC);
|
||||
@@ -1256,6 +1237,8 @@ bool TWorld::Update()
|
||||
|
||||
Ground.CheckQuery();
|
||||
|
||||
Ground.Update_Lights();
|
||||
|
||||
if( Train != nullptr ) {
|
||||
TSubModel::iInstance = reinterpret_cast<int>( Train->Dynamic() );
|
||||
Train->Update( dt );
|
||||
@@ -1275,13 +1258,6 @@ bool TWorld::Update()
|
||||
( Train->Dynamic()->fShade <= 0.0 ?
|
||||
( Global::fLuminance <= 0.5 ) :
|
||||
( Train->Dynamic()->fShade * Global::fLuminance <= 0.5 ) ) );
|
||||
|
||||
// match the vehicle light position with new position of the vehicle
|
||||
Global::VehicleLight.set_position( Train->Dynamic()->GetPosition() + ( Train->Dynamic()->VectorFront() * Train->Dynamic()->GetLength() * 0.45 ) );
|
||||
Global::VehicleLight.direction = Train->Dynamic()->VectorFront();
|
||||
Global::VehicleLightRear.set_position( Train->Dynamic()->GetPosition() - ( Train->Dynamic()->VectorFront() * Train->Dynamic()->GetLength() * 0.45 ) );
|
||||
Global::VehicleLightRear.direction = Train->Dynamic()->VectorFront();
|
||||
Global::VehicleLightRear.direction.RotateY( M_PI );
|
||||
}
|
||||
|
||||
m_init = true;
|
||||
@@ -1556,78 +1532,11 @@ bool TWorld::Render()
|
||||
Environment.render();
|
||||
}
|
||||
|
||||
// enable vehicle light, if it's present and on
|
||||
if( nullptr != Train ) {
|
||||
if( false == Ground.Render( Camera.Pos ) ) { return false; }
|
||||
|
||||
auto const &frontlights = Train->Controlled()->iLights[ 0 ];
|
||||
int const frontlightcount = 0 +
|
||||
( ( frontlights & 1 ) ? 1 : 0 ) +
|
||||
( ( frontlights & 4 ) ? 1 : 0 ) +
|
||||
( ( frontlights & 16 ) ? 1 : 0 );
|
||||
|
||||
if( ( true == Train->Controlled()->Battery )
|
||||
&& ( frontlightcount > 0 ) ) {
|
||||
// halogen light. TODO: allow light type definition
|
||||
Global::VehicleLight.ambient[ 0 ] = 0.15f * 255.0 * frontlightcount / 255.0;
|
||||
Global::VehicleLight.ambient[ 1 ] = 0.15f * 241.0 * frontlightcount / 255.0;
|
||||
Global::VehicleLight.ambient[ 2 ] = 0.15f * 224.0 * frontlightcount / 255.0;
|
||||
|
||||
::glLightf( opengl_renderer::vehiclelight, GL_LINEAR_ATTENUATION, 0.3f / pow(frontlightcount, 2) );
|
||||
glEnable( GfxRenderer.vehiclelight );
|
||||
Global::VehicleLight.apply_intensity();
|
||||
Global::VehicleLight.apply_angle();
|
||||
}
|
||||
else {
|
||||
glDisable( GfxRenderer.vehiclelight );
|
||||
}
|
||||
auto const &rearlights = Train->Controlled()->iLights[ 1 ];
|
||||
int const rearlightcount = 0 +
|
||||
( ( rearlights & 1 ) ? 1 : 0 ) +
|
||||
( ( rearlights & 4 ) ? 1 : 0 ) +
|
||||
( ( rearlights & 16 ) ? 1 : 0 );
|
||||
|
||||
if( ( true == Train->Controlled()->Battery )
|
||||
&& ( rearlightcount > 0 ) ) {
|
||||
// halogen light. TODO: allow light type definition
|
||||
Global::VehicleLightRear.ambient[ 0 ] = 0.15f * 255.0 * rearlightcount / 255.0;
|
||||
Global::VehicleLightRear.ambient[ 1 ] = 0.15f * 241.0 * rearlightcount / 255.0;
|
||||
Global::VehicleLightRear.ambient[ 2 ] = 0.15f * 224.0 * rearlightcount / 255.0;
|
||||
|
||||
::glLightf( opengl_renderer::vehiclelightrear, GL_LINEAR_ATTENUATION, 0.3f / pow( rearlightcount, 2 ) );
|
||||
glEnable( GfxRenderer.vehiclelightrear );
|
||||
Global::VehicleLightRear.apply_intensity();
|
||||
Global::VehicleLightRear.apply_angle();
|
||||
}
|
||||
else {
|
||||
glDisable( GfxRenderer.vehiclelightrear );
|
||||
}
|
||||
}
|
||||
|
||||
if (Global::bUseVBO)
|
||||
{ // renderowanie przez VBO
|
||||
if (!Ground.RenderVBO(Camera.Pos))
|
||||
return false;
|
||||
if (!Ground.RenderAlphaVBO(Camera.Pos))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{ // renderowanie przez Display List
|
||||
if (!Ground.RenderDL(Camera.Pos))
|
||||
return false;
|
||||
if (!Ground.RenderAlphaDL(Camera.Pos))
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
TSubModel::iInstance = (int)(Train ? Train->Dynamic() : 0); //żeby nie robić cudzych animacji
|
||||
// if (Camera.Type==tp_Follow)
|
||||
if (Train)
|
||||
Train->Update();
|
||||
*/
|
||||
Render_Cab();
|
||||
Render_UI();
|
||||
|
||||
// glFlush();
|
||||
// Global::bReCompile=false; //Ra: już zrobiona rekompilacja
|
||||
ResourceManager::Sweep( Timer::GetSimulationTime() );
|
||||
|
||||
return true;
|
||||
@@ -1652,6 +1561,7 @@ TWorld::Render_Cab() {
|
||||
// ABu: Rendering kabiny jako ostatniej, zeby bylo widac przez szyby, tylko w widoku ze srodka
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
// ABu: Rendering kabiny jako ostatniej, zeby bylo widac przez szyby, tylko w widoku ze srodka
|
||||
if( ( Train->Dynamic()->mdKabina != Train->Dynamic()->mdModel ) &&
|
||||
@@ -1777,18 +1687,18 @@ TWorld::Render_Cab() {
|
||||
glEnable( GL_FOG );
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
glEnable( GL_LIGHTING ); // po renderowaniu smugi jest to wyłączone
|
||||
// Ra: pojazd użytkownika należało by renderować po smudze, aby go nie rozświetlała
|
||||
|
||||
Global::bSmudge = false; // aby model użytkownika się teraz wyrenderował
|
||||
dynamic->Render();
|
||||
dynamic->RenderAlpha(); // przezroczyste fragmenty pojazdów na torach
|
||||
/*
|
||||
|
||||
} // yB: moje smuuugi 1 - koniec
|
||||
else
|
||||
glEnable( GL_LIGHTING ); // po renderowaniu drutów może być to wyłączone. TODO: have the wires render take care of its own shit
|
||||
*/
|
||||
*/ glEnable( GL_LIGHTING ); // po renderowaniu drutów może być to wyłączone. TODO: have the wires render take care of its own shit
|
||||
|
||||
if( dynamic->mdKabina ) // bo mogła zniknąć przy przechodzeniu do innego pojazdu
|
||||
{
|
||||
#ifdef EU07_USE_OLD_LIGHTING_MODEL
|
||||
@@ -1874,10 +1784,6 @@ TWorld::Render_Cab() {
|
||||
glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuseCabLight );
|
||||
glLightfv( GL_LIGHT0, GL_SPECULAR, specularCabLight );
|
||||
#else
|
||||
// cab shouldn't get affected by the vehicle light, so we disable it here
|
||||
::glDisable( GfxRenderer.vehiclelight );
|
||||
::glDisable( GfxRenderer.vehiclelightrear );
|
||||
|
||||
if( dynamic->InteriorLightLevel > 0.0f ) {
|
||||
|
||||
// crude way to light the cabin, until we have something more complete in place
|
||||
|
||||
10
dumb3d.h
10
dumb3d.h
@@ -83,7 +83,8 @@ class vector3
|
||||
|
||||
void inline Normalize();
|
||||
void inline SafeNormalize();
|
||||
double inline Length();
|
||||
double inline Length() const;
|
||||
double inline LengthSquared() const;
|
||||
void inline Zero()
|
||||
{
|
||||
x = y = z = 0.0;
|
||||
@@ -435,11 +436,16 @@ void inline vector3::Normalize()
|
||||
z *= il;
|
||||
}
|
||||
|
||||
double inline vector3::Length()
|
||||
double inline vector3::Length() const
|
||||
{
|
||||
return SQRT_FUNCTION(x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
double inline vector3::LengthSquared() const {
|
||||
|
||||
return ( x * x + y * y + z * z );
|
||||
}
|
||||
|
||||
inline bool operator==(const matrix4x4 &m1, const matrix4x4 &m2)
|
||||
{
|
||||
for (int x = 0; x < 4; ++x)
|
||||
|
||||
75
lightarray.cpp
Normal file
75
lightarray.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/*
|
||||
MaSzyna EU07 locomotive simulator
|
||||
Copyright (C) 2001-2004 Marcin Wozniak and others
|
||||
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "lightarray.h"
|
||||
#include "dynobj.h"
|
||||
|
||||
void
|
||||
light_array::insert( TDynamicObject const *Owner ) {
|
||||
|
||||
// we're only storing lights for locos, which have two sets of lights, front and rear
|
||||
// for a more generic role this function would have to be tweaked to add vehicle type-specific light combinations
|
||||
data.emplace_back( Owner, 0 );
|
||||
data.emplace_back( Owner, 1 );
|
||||
}
|
||||
|
||||
void
|
||||
light_array::remove( TDynamicObject const *Owner ) {
|
||||
|
||||
data.erase(
|
||||
std::remove_if(
|
||||
data.begin(),
|
||||
data.end(),
|
||||
[=]( light_record const &light ){ return light.owner == Owner; } ),
|
||||
data.end() );
|
||||
}
|
||||
|
||||
// updates records in the collection
|
||||
void
|
||||
light_array::update() {
|
||||
|
||||
for( auto &light : data ) {
|
||||
// update light parameters to match current data of the owner
|
||||
if( light.index == 0 ) {
|
||||
// front light set
|
||||
light.position = light.owner->GetPosition() + ( light.owner->VectorFront() * light.owner->GetLength() * 0.45 );
|
||||
light.direction = light.owner->VectorFront();
|
||||
}
|
||||
else {
|
||||
// rear light set
|
||||
light.position = light.owner->GetPosition() - ( light.owner->VectorFront() * light.owner->GetLength() * 0.45 );
|
||||
light.direction = light.owner->VectorFront();
|
||||
light.direction.x = -light.direction.x;
|
||||
light.direction.z = -light.direction.z;
|
||||
}
|
||||
// determine intensity of this light set
|
||||
if( true == light.owner->MoverParameters->Battery ) {
|
||||
// with battery on, the intensity depends on the state of activated switches
|
||||
auto const &lightbits = light.owner->iLights[ light.index ];
|
||||
light.count = 0 +
|
||||
( ( lightbits & 1 ) ? 1 : 0 ) +
|
||||
( ( lightbits & 4 ) ? 1 : 0 ) +
|
||||
( ( lightbits & 16 ) ? 1 : 0 );
|
||||
|
||||
light.intensity = 0.15f * light.count; // TODO: intensity can be affected further by dim switch or other factors
|
||||
}
|
||||
else {
|
||||
// with battery off the lights are off
|
||||
light.intensity = 0.0f;
|
||||
light.count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
45
lightarray.h
Normal file
45
lightarray.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "dumb3d.h"
|
||||
#include "float3d.h"
|
||||
#include "dynobj.h"
|
||||
|
||||
// collection of virtual light sources present in the scene
|
||||
// used by the renderer to determine most suitable placement for actual light sources during render
|
||||
struct light_array {
|
||||
|
||||
public:
|
||||
// types
|
||||
struct light_record {
|
||||
|
||||
light_record( TDynamicObject const *Owner, int const Lightindex) :
|
||||
owner(Owner), index(Lightindex)
|
||||
{};
|
||||
|
||||
TDynamicObject const *owner; // the object in world which 'carries' the light
|
||||
int index{ -1 }; // 0: front lights, 1: rear lights
|
||||
Math3D::vector3 position; // position of the light in 3d scene
|
||||
Math3D::vector3 direction; // direction of the light in 3d scene
|
||||
float3 color{ 255.0f / 255.0f, 241.0f / 255.0f, 224.0f / 255.0f }; // color of the light, default is halogen light
|
||||
float intensity{ 0.0f }; // (combined) intensity of the light(s)
|
||||
int count{ 0 }; // number (or pattern) of active light(s)
|
||||
};
|
||||
|
||||
// methods
|
||||
// adds records for lights of specified owner to the collection
|
||||
void
|
||||
insert( TDynamicObject const *Owner );
|
||||
// removes records for lights of specified owner from the collection
|
||||
void
|
||||
remove( TDynamicObject const *Owner );
|
||||
// updates records in the collection
|
||||
void
|
||||
update();
|
||||
|
||||
// types
|
||||
typedef std::vector<light_record> lightrecord_array;
|
||||
|
||||
// members
|
||||
lightrecord_array data;
|
||||
};
|
||||
@@ -104,6 +104,7 @@
|
||||
<ClCompile Include="Gauge.cpp" />
|
||||
<ClCompile Include="Globals.cpp" />
|
||||
<ClCompile Include="Ground.cpp" />
|
||||
<ClCompile Include="lightarray.cpp" />
|
||||
<ClCompile Include="Logs.cpp" />
|
||||
<ClCompile Include="mczapkie\friction.cpp" />
|
||||
<ClCompile Include="mczapkie\hamulce.cpp" />
|
||||
@@ -166,6 +167,7 @@
|
||||
<ClInclude Include="Gauge.h" />
|
||||
<ClInclude Include="Globals.h" />
|
||||
<ClInclude Include="Ground.h" />
|
||||
<ClInclude Include="lightarray.h" />
|
||||
<ClInclude Include="Logs.h" />
|
||||
<ClInclude Include="McZapkie\friction.h" />
|
||||
<ClInclude Include="McZapkie\hamulce.h" />
|
||||
@@ -222,4 +224,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -201,6 +201,9 @@
|
||||
<ClCompile Include="stars.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="lightarray.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="opengl\glew.h">
|
||||
@@ -392,6 +395,9 @@
|
||||
<ClInclude Include="stars.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="lightarray.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="maszyna.rc">
|
||||
|
||||
78
renderer.cpp
78
renderer.cpp
@@ -9,7 +9,85 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "renderer.h"
|
||||
#include "globals.h"
|
||||
|
||||
opengl_renderer GfxRenderer;
|
||||
|
||||
void
|
||||
opengl_renderer::Init() {
|
||||
|
||||
// create dynamic light pool
|
||||
for( int idx = 0; idx < Global::DynamicLightCount; ++idx ) {
|
||||
|
||||
opengl_light light;
|
||||
light.id = GL_LIGHT1 + idx;
|
||||
|
||||
light.position[ 3 ] = 1.0f;
|
||||
::glLightf( light.id, GL_SPOT_CUTOFF, 20.0f );
|
||||
::glLightf( light.id, GL_SPOT_EXPONENT, 10.0f );
|
||||
::glLightf( light.id, GL_CONSTANT_ATTENUATION, 0.0f );
|
||||
::glLightf( light.id, GL_LINEAR_ATTENUATION, 0.035f );
|
||||
|
||||
m_lights.emplace_back( light );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::Update_Lights( light_array const &Lights ) {
|
||||
|
||||
int const count = std::min( m_lights.size(), Lights.data.size() );
|
||||
if( count == 0 ) { return; }
|
||||
|
||||
auto renderlight = m_lights.begin();
|
||||
|
||||
for( auto const &scenelight : Lights.data ) {
|
||||
|
||||
if( renderlight == m_lights.end() ) {
|
||||
// we ran out of lights to assign
|
||||
break;
|
||||
}
|
||||
if( scenelight.intensity == 0.0f ) {
|
||||
// all lights past this one are bound to be off
|
||||
break;
|
||||
}
|
||||
if( ( Global::pCameraPosition - scenelight.position ).Length() > 1000.0f ) {
|
||||
// we don't care about lights past arbitrary limit of 1 km.
|
||||
// but there could still be weaker lights which are closer, so keep looking
|
||||
continue;
|
||||
}
|
||||
// if the light passed tests so far, it's good enough
|
||||
renderlight->set_position( scenelight.position );
|
||||
renderlight->direction = scenelight.direction;
|
||||
|
||||
renderlight->diffuse[ 0 ] = scenelight.color.x;
|
||||
renderlight->diffuse[ 1 ] = scenelight.color.y;
|
||||
renderlight->diffuse[ 2 ] = scenelight.color.z;
|
||||
renderlight->ambient[ 0 ] = scenelight.color.x * scenelight.intensity;
|
||||
renderlight->ambient[ 1 ] = scenelight.color.y * scenelight.intensity;
|
||||
renderlight->ambient[ 2 ] = scenelight.color.z * scenelight.intensity;
|
||||
|
||||
::glLightf( renderlight->id, GL_LINEAR_ATTENUATION, 0.3f / std::pow( scenelight.count, 2 ) );
|
||||
::glEnable( renderlight->id );
|
||||
|
||||
renderlight->apply_intensity();
|
||||
renderlight->apply_angle();
|
||||
|
||||
++renderlight;
|
||||
}
|
||||
|
||||
while( renderlight != m_lights.end() ) {
|
||||
// if we went through all scene lights and there's still opengl lights remaining, kill these
|
||||
::glDisable( renderlight->id );
|
||||
++renderlight;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::Disable_Lights() {
|
||||
|
||||
for( int idx = 0; idx < m_lights.size() + 1; ++idx ) {
|
||||
|
||||
::glDisable( GL_LIGHT0 + idx );
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
34
renderer.h
34
renderer.h
@@ -11,6 +11,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "opengl/glew.h"
|
||||
#include "texture.h"
|
||||
#include "lightarray.h"
|
||||
#include "dumb3d.h"
|
||||
|
||||
struct opengl_light {
|
||||
@@ -23,10 +24,10 @@ struct opengl_light {
|
||||
GLfloat specular[ 4 ];
|
||||
|
||||
opengl_light() {
|
||||
position[ 0 ] = position[ 1 ] = position[ 2 ] = 0.0f; position[ 3 ] = 1.0f;
|
||||
ambient[ 0 ] = ambient[ 1 ] = ambient[ 2 ] = 0.0f; ambient[ 3 ] = 1.0f;
|
||||
diffuse[ 0 ] = diffuse[ 1 ] = diffuse[ 2 ] = diffuse[ 3 ] = 1.0f;
|
||||
specular[ 0 ] = specular[ 1 ] = specular[ 2 ] = specular[ 3 ] = 1.0f;
|
||||
position[ 0 ] = position[ 1 ] = position[ 2 ] = 0.0f; position[ 3 ] = 1.0f; // 0,0,0,1
|
||||
ambient[ 0 ] = ambient[ 1 ] = ambient[ 2 ] = 0.0f; ambient[ 3 ] = 1.0f; // 0,0,0,1
|
||||
diffuse[ 0 ] = diffuse[ 1 ] = diffuse[ 2 ] = diffuse[ 3 ] = 1.0f; // 1,1,1,1
|
||||
specular[ 0 ] = specular[ 1 ] = specular[ 2 ] = specular[ 3 ] = 1.0f; // 1,1,1,1
|
||||
}
|
||||
|
||||
inline
|
||||
@@ -72,33 +73,50 @@ struct opengl_material {
|
||||
class opengl_renderer {
|
||||
|
||||
public:
|
||||
GLenum static const sunlight{ GL_LIGHT0 };
|
||||
GLenum static const vehiclelight{ GL_LIGHT1 };
|
||||
GLenum static const vehiclelightrear{ GL_LIGHT2 };
|
||||
// types
|
||||
|
||||
// methods
|
||||
void
|
||||
Init();
|
||||
|
||||
void
|
||||
Update_Lights( light_array const &Lights );
|
||||
|
||||
void
|
||||
Disable_Lights();
|
||||
|
||||
texture_manager::size_type
|
||||
GetTextureId( std::string Filename, std::string const &Dir, int const Filter = -1, bool const Loadnow = true ) {
|
||||
|
||||
return m_textures.GetTextureId( Filename, Dir, Filter, Loadnow );
|
||||
}
|
||||
|
||||
void
|
||||
Bind( texture_manager::size_type const Id ) {
|
||||
// temporary until we separate the renderer
|
||||
m_textures.Bind( Id );
|
||||
}
|
||||
|
||||
opengl_texture &
|
||||
Texture( texture_manager::size_type const Id ) {
|
||||
|
||||
return m_textures.Texture( Id );
|
||||
}
|
||||
|
||||
// members
|
||||
GLenum static const sunlight{ GL_LIGHT0 };
|
||||
|
||||
private:
|
||||
// types
|
||||
enum class rendermode {
|
||||
color
|
||||
};
|
||||
|
||||
typedef std::vector<opengl_light> opengllight_array;
|
||||
|
||||
// members
|
||||
rendermode renderpass{ rendermode::color };
|
||||
|
||||
opengllight_array m_lights;
|
||||
texture_manager m_textures;
|
||||
};
|
||||
|
||||
|
||||
4
sky.cpp
4
sky.cpp
@@ -36,7 +36,7 @@ void TSky::Render( float3 const &Tint )
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
|
||||
#else
|
||||
::glEnable( GL_LIGHTING );
|
||||
::glDisable( GL_LIGHT0 );
|
||||
GfxRenderer.Disable_Lights();
|
||||
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, &Tint.x );
|
||||
#endif
|
||||
if (Global::bUseVBO)
|
||||
@@ -56,7 +56,7 @@ void TSky::Render( float3 const &Tint )
|
||||
#else
|
||||
GLfloat noambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, noambient );
|
||||
::glEnable( GL_LIGHT0 );
|
||||
::glEnable( GL_LIGHT0 ); // other lights will be enabled during lights update
|
||||
::glDisable( GL_LIGHTING );
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user