16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-22 09:19:18 +02:00

Merge branch 'mover_in_c++'

This commit is contained in:
firleju
2017-06-29 19:43:24 +02:00
22 changed files with 272 additions and 210 deletions

View File

@@ -539,11 +539,10 @@ TDynamicObject::toggle_lights() {
SectionLightsActive = false; SectionLightsActive = false;
} }
else { else {
std::string compartmentname;
// set lights with probability depending on the compartment type. TODO: expose this in .mmd file // set lights with probability depending on the compartment type. TODO: expose this in .mmd file
for( auto &sectionlight : SectionLightLevels ) { for( auto &sectionlight : SectionLightLevels ) {
compartmentname = sectionlight.compartment->pName; std::string const &compartmentname = sectionlight.compartment->pName;
if( ( compartmentname.find( "corridor" ) != std::string::npos ) if( ( compartmentname.find( "corridor" ) != std::string::npos )
|| ( compartmentname.find( "korytarz" ) != std::string::npos ) ) { || ( compartmentname.find( "korytarz" ) != std::string::npos ) ) {
// corridors are lit 100% of time // corridors are lit 100% of time
@@ -584,8 +583,9 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
pAnimations[i].yUpdate(pAnimations + pAnimations[i].yUpdate(pAnimations +
i); // aktualizacja animacji (położenia submodeli i); // aktualizacja animacji (położenia submodeli
*/ */
if( ObjSqrDist < 2500 ) // gdy bliżej niż 50m if( ( mdModel != nullptr )
{ && ( ObjSqrDist < 2500 ) ) {
// gdy bliżej niż 50m
// ABu290105: rzucanie pudlem // ABu290105: rzucanie pudlem
// te animacje wymagają bananów w modelach! // te animacje wymagają bananów w modelach!
mdModel->GetSMRoot()->SetTranslate(modelShake); mdModel->GetSMRoot()->SetTranslate(modelShake);
@@ -4033,12 +4033,17 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
bool Stop_InternalData = false; bool Stop_InternalData = false;
pants = NULL; // wskaźnik pierwszego obiektu animującego dla pantografów pants = NULL; // wskaźnik pierwszego obiektu animującego dla pantografów
cParser parser( TypeName + ".mmd", cParser::buffer_FILE, BaseDir ); cParser parser( TypeName + ".mmd", cParser::buffer_FILE, BaseDir );
if( false == parser.ok() ) {
ErrorLog( "Failed to load appearance data for vehicle " + MoverParameters->Name );
return;
}
std::string token; std::string token;
do { do {
token = ""; token = "";
parser.getTokens(); parser >> token; parser.getTokens(); parser >> token;
if( token == "models:") { if( ( token == "models:" )
|| ( token == "models:" ) ) { // crude way to handle utf8 bom potentially appearing before the first token
// modele i podmodele // modele i podmodele
m_materialdata.multi_textures = 0; // czy jest wiele tekstur wymiennych? m_materialdata.multi_textures = 0; // czy jest wiele tekstur wymiennych?
parser.getTokens(); parser.getTokens();
@@ -5024,13 +5029,12 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
} }
if (mdModel) if (mdModel)
mdModel->Init(); // obrócenie modelu oraz optymalizacja, również zapisanie mdModel->Init(); // obrócenie modelu oraz optymalizacja, również zapisanie binarnego
// binarnego
if (mdLoad) if (mdLoad)
mdLoad->Init(); mdLoad->Init();
if (mdLowPolyInt) if (mdLowPolyInt)
mdLowPolyInt->Init(); mdLowPolyInt->Init();
// sHorn2.CopyIfEmpty(sHorn1); ///żeby jednak trąbił też drugim
Global::asCurrentTexturePath = szTexturePath; // kiedyś uproszczone wnętrze mieszało tekstury nieba Global::asCurrentTexturePath = szTexturePath; // kiedyś uproszczone wnętrze mieszało tekstury nieba
} }

View File

@@ -82,13 +82,10 @@ GLfloat Global::AtmoColor[] = {0.423f, 0.702f, 1.0f};
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;
float Global::Overcast{ 0.1f }; // NOTE: all this weather stuff should be moved elsewhere float Global::Overcast { 0.1f }; // NOTE: all this weather stuff should be moved elsewhere
opengl_light Global::DayLight; opengl_light Global::DayLight;
int Global::DynamicLightCount{ 3 }; int Global::DynamicLightCount { 3 };
GLfloat Global::whiteLight[] = {1.00f, 1.00f, 1.00f, 1.0f}; bool Global::ScaleSpecularValues { true };
GLfloat Global::noLight[] = {0.00f, 0.00f, 0.00f, 1.0f};
GLfloat Global::darkLight[] = {0.03f, 0.03f, 0.03f, 1.0f}; //śladowe
GLfloat Global::lightPos[4];
bool Global::bRollFix = true; // czy wykonać przeliczanie przechyłki bool Global::bRollFix = true; // czy wykonać przeliczanie przechyłki
bool Global::bJoinEvents = false; // czy grupować eventy o tych samych nazwach bool Global::bJoinEvents = false; // czy grupować eventy o tych samych nazwach
int Global::iHiddenEvents = 1; // czy łączyć eventy z torami poprzez nazwę toru int Global::iHiddenEvents = 1; // czy łączyć eventy z torami poprzez nazwę toru
@@ -224,13 +221,6 @@ std::string Global::GetNextSymbol()
void Global::LoadIniFile(std::string asFileName) void Global::LoadIniFile(std::string asFileName)
{ {
/*
for (int i = 0; i < 10; ++i)
{ // zerowanie pozycji kamer
pFreeCameraInit[i] = vector3(0, 0, 0); // współrzędne w scenerii
pFreeCameraInitAngle[i] = vector3(0, 0, 0); // kąty obrotu w radianach
}
*/
FreeCameraInit.resize( 10 ); FreeCameraInit.resize( 10 );
FreeCameraInitAngle.resize( 10 ); FreeCameraInitAngle.resize( 10 );
cParser parser(asFileName, cParser::buffer_FILE); cParser parser(asFileName, cParser::buffer_FILE);
@@ -543,6 +533,11 @@ void Global::ConfigParse(cParser &Parser)
// max 8 lights per opengl specs, minus one used for sun. at least one light for controlled vehicle // max 8 lights per opengl specs, minus one used for sun. at least one light for controlled vehicle
Global::DynamicLightCount = clamp( Global::DynamicLightCount, 1, 7 ); Global::DynamicLightCount = clamp( Global::DynamicLightCount, 1, 7 );
} }
else if( token == "scalespeculars" ) {
// whether strength of specular highlights should be adjusted (generally needed for legacy 3d models)
Parser.getTokens();
Parser >> Global::ScaleSpecularValues;
}
else if (token == "smoothtraction") else if (token == "smoothtraction")
{ {
// podwójna jasność ambient // podwójna jasność ambient

View File

@@ -225,11 +225,8 @@ class Global
// TODO: put these things in the renderer // TODO: put these things in the renderer
static opengl_light DayLight; static opengl_light DayLight;
static int DynamicLightCount; static int DynamicLightCount;
static bool ScaleSpecularValues;
static GLfloat whiteLight[];
static GLfloat noLight[];
static GLfloat darkLight[];
static GLfloat lightPos[4];
static int iSlowMotion; static int iSlowMotion;
static TDynamicObject *changeDynObj; static TDynamicObject *changeDynObj;
static double ABuDebug; static double ABuDebug;

View File

@@ -1937,7 +1937,7 @@ bool TGround::Init(std::string File)
>> Global::DayLight.direction.x >> Global::DayLight.direction.x
>> Global::DayLight.direction.y >> Global::DayLight.direction.y
>> Global::DayLight.direction.z;; >> Global::DayLight.direction.z;;
Global::DayLight.direction.Normalize(); Global::DayLight.direction = glm::normalize( Global::DayLight.direction );
parser.getTokens(9, false); parser.getTokens(9, false);
do { do {

View File

@@ -240,8 +240,13 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
if (eType < TP_ROTATOR) if (eType < TP_ROTATOR)
readColor(parser, f4Ambient); // ignoruje token przed readColor(parser, f4Ambient); // ignoruje token przed
readColor(parser, f4Diffuse); readColor(parser, f4Diffuse);
if (eType < TP_ROTATOR) if( eType < TP_ROTATOR ) {
readColor(parser, f4Specular); readColor( parser, f4Specular );
if( pName == "cien" ) {
// crude workaround to kill specular on shadow geometry of legacy models
f4Specular = glm::vec4{ 0.0f, 0.0f, 0.0f, 1.0f };
}
}
parser.ignoreTokens(1); // zignorowanie nazwy "SelfIllum:" parser.ignoreTokens(1); // zignorowanie nazwy "SelfIllum:"
{ {
std::string light = parser.getToken<std::string>(); std::string light = parser.getToken<std::string>();
@@ -367,6 +372,10 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
readMatrix(parser, *fMatrix); // wczytanie transform readMatrix(parser, *fMatrix); // wczytanie transform
if (!fMatrix->IdentityIs()) if (!fMatrix->IdentityIs())
iFlags |= 0x8000; // transform niejedynkowy - trzeba go przechować iFlags |= 0x8000; // transform niejedynkowy - trzeba go przechować
if( std::abs( Det( *fMatrix ) - 1.0f ) > 0.01f ) {
ErrorLog( "Bad model: transformation matrix for sub-model \"" + pName + "\" imposes geometry scaling (factor: " + to_string( Det( *fMatrix ), 2 ) + ")" );
m_normalizenormals = true;
}
if (eType < TP_ROTATOR) if (eType < TP_ROTATOR)
{ // wczytywanie wierzchołków { // wczytywanie wierzchołków
parser.getTokens(2, false); parser.getTokens(2, false);
@@ -446,7 +455,7 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
--facecount; // o jeden trójkąt mniej --facecount; // o jeden trójkąt mniej
iNumVerts -= 3; // czyli o 3 wierzchołki iNumVerts -= 3; // czyli o 3 wierzchołki
i -= 3; // wczytanie kolejnego w to miejsce i -= 3; // wczytanie kolejnego w to miejsce
WriteLog("Degenerated triangle ignored in: \"" + pName + "\", vertice " + std::to_string(i)); WriteLog("Bad model: degenerated triangle ignored in: \"" + pName + "\", vertices " + std::to_string(i) + "-" + std::to_string(i+2));
} }
if (i > 0) { if (i > 0) {
// jeśli pierwszy trójkąt będzie zdegenerowany, to zostanie usunięty i nie ma co sprawdzać // jeśli pierwszy trójkąt będzie zdegenerowany, to zostanie usunięty i nie ma co sprawdzać
@@ -458,7 +467,7 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
--facecount; // o jeden trójkąt mniej --facecount; // o jeden trójkąt mniej
iNumVerts -= 3; // czyli o 3 wierzchołki iNumVerts -= 3; // czyli o 3 wierzchołki
i -= 3; // wczytanie kolejnego w to miejsce i -= 3; // wczytanie kolejnego w to miejsce
WriteLog( "Too large triangle ignored in: \"" + pName + "\"" ); WriteLog( "Bad model: too large triangle ignored in: \"" + pName + "\"" );
} }
} }
} }
@@ -474,7 +483,7 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
Vertices[ i * 3 ].position - Vertices[ i * 3 + 1 ].position, Vertices[ i * 3 ].position - Vertices[ i * 3 + 1 ].position,
Vertices[ i * 3 ].position - Vertices[ i * 3 + 2 ].position ); Vertices[ i * 3 ].position - Vertices[ i * 3 + 2 ].position );
facenormals.emplace_back( facenormals.emplace_back(
glm::length( facenormal ) > 0.0f ? glm::length2( facenormal ) > 0.0f ?
glm::normalize( facenormal ) : glm::normalize( facenormal ) :
glm::vec3() ); glm::vec3() );
} }
@@ -492,16 +501,24 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
auto adjacenvertextidx = vertexidx; // zaczynamy dodawanie wektorów normalnych od własnego auto adjacenvertextidx = vertexidx; // zaczynamy dodawanie wektorów normalnych od własnego
while (adjacenvertextidx >= 0) { while (adjacenvertextidx >= 0) {
// sumowanie z wektorem normalnym sąsiada (włącznie ze sobą) // sumowanie z wektorem normalnym sąsiada (włącznie ze sobą)
wsp[adjacenvertextidx] = vertexidx; // informacja, że w tym wierzchołku jest już policzony wektor normalny if( glm::dot( vertexnormal, facenormals[ adjacenvertextidx / 3 ] ) > -0.99f ) {
vertexnormal += facenormals[adjacenvertextidx / 3]; wsp[ adjacenvertextidx ] = vertexidx; // informacja, że w tym wierzchołku jest już policzony wektor normalny
vertexnormal += facenormals[ adjacenvertextidx / 3 ];
}
else {
ErrorLog( "Bad model: opposite normals in the same smoothing group, check sub-model \"" + pName + "\" for two-sided faces and/or scaling" );
}
// i szukanie od kolejnego trójkąta // i szukanie od kolejnego trójkąta
adjacenvertextidx = SeekFaceNormal(sg, adjacenvertextidx / 3 + 1, sg[faceidx], Vertices[vertexidx].position, Vertices); adjacenvertextidx = SeekFaceNormal(sg, adjacenvertextidx / 3 + 1, sg[faceidx], Vertices[vertexidx].position, Vertices);
} }
// Ra 15-01: należało by jeszcze uwzględnić skalowanie wprowadzane przez transformy, aby normalne po przeskalowaniu były jednostkowe // Ra 15-01: należało by jeszcze uwzględnić skalowanie wprowadzane przez transformy, aby normalne po przeskalowaniu były jednostkowe
if( glm::length2( vertexnormal ) == 0.0f ) {
WriteLog( "Bad model: zero lenght normal vector generated for sub-model \"" + pName + "\"" );
}
Vertices[ vertexidx ].normal = ( Vertices[ vertexidx ].normal = (
glm::length( vertexnormal ) > 0.0f ? glm::length2( vertexnormal ) > 0.0f ?
glm::normalize( vertexnormal ) : glm::normalize( vertexnormal ) :
glm::vec3() ); // przepisanie do wierzchołka trójkąta facenormals[ vertexidx / 3 ] ); // przepisanie do wierzchołka trójkąta
} }
} }
Vertices.resize( iNumVerts ); // in case we had some degenerate triangles along the way Vertices.resize( iNumVerts ); // in case we had some degenerate triangles along the way
@@ -1516,6 +1533,15 @@ void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
iNumVerts += submodel.iNumVerts; iNumVerts += submodel.iNumVerts;
for( auto &vertex : vertices ) { for( auto &vertex : vertices ) {
vertex.deserialize( s ); vertex.deserialize( s );
if( submodel.eType < TP_ROTATOR ) {
// normal vectors debug routine
auto normallength = glm::length2( vertex.normal );
if( ( false == submodel.m_normalizenormals )
&& ( std::abs( normallength - 1.0f ) > 0.01f ) ) {
submodel.m_normalizenormals = true;
WriteLog( "Bad model: non-unit normal vector(s) encountered during sub-model geometry deserialization" );
}
}
} }
// remap geometry type for custom type submodels // remap geometry type for custom type submodels
int type; int type;
@@ -1599,6 +1625,7 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
Child = (iChild > 0) ? s + iChild : nullptr; // zerowy nie może być potomnym Child = (iChild > 0) ? s + iChild : nullptr; // zerowy nie może być potomnym
Next = (iNext > 0) ? s + iNext : nullptr; // zerowy nie może być następnym Next = (iNext > 0) ? s + iNext : nullptr; // zerowy nie może być następnym
fMatrix = ((iMatrix >= 0) && m) ? m + iMatrix : nullptr; fMatrix = ((iMatrix >= 0) && m) ? m + iMatrix : nullptr;
if (n->size() && (iName >= 0)) if (n->size() && (iName >= 0))
{ {
pName = n->at(iName); pName = n->at(iName);
@@ -1612,12 +1639,16 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
// obiektem "Light_Off" // obiektem "Light_Off"
else if (dynamic) else if (dynamic)
{ // inaczej wyłączało smugę w latarniach { // inaczej wyłączało smugę w latarniach
if ((pName.size() >= 3) && (pName.substr(pName.size() - 3, 3) == "_on")) if ((pName.size() >= 3) && (pName.substr(pName.size() - 3, 3) == "_on")) {
{ // jeśli jest kontrolką w stanie zapalonym // jeśli jest kontrolką w stanie zapalonym to domyślnie wyłączyć,
iVisible = 0; // to domyślnie wyłączyć, żeby się nie nakładało z // żeby się nie nakładało z obiektem "_off"
iVisible = 0;
} }
} }
// obiektem "_off" // hack: reset specular light value for shadow submodels
if( pName == "cien" ) {
f4Specular = glm::vec4 { 0.0f, 0.0f, 0.0f, 1.0f };
}
} }
} }
else else
@@ -1654,11 +1685,22 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
if( fCosHotspotAngle > 1.0f ) { if( fCosHotspotAngle > 1.0f ) {
fCosHotspotAngle = std::cos( DegToRad( 0.5f * fCosHotspotAngle ) ); fCosHotspotAngle = std::cos( DegToRad( 0.5f * fCosHotspotAngle ) );
} }
// cap specular values for legacy models
f4Specular = glm::vec4{
clamp( f4Specular.r, 0.0f, 1.0f ),
clamp( f4Specular.g, 0.0f, 1.0f ),
clamp( f4Specular.b, 0.0f, 1.0f ),
clamp( f4Specular.a, 0.0f, 1.0f ) };
iFlags &= ~0x0200; // wczytano z pliku binarnego (nie jest właścicielem tablic) iFlags &= ~0x0200; // wczytano z pliku binarnego (nie jest właścicielem tablic)
/*
iVboPtr = tVboPtr; if( ( fMatrix != nullptr )
*/ && ( std::abs( Det( *fMatrix ) - 1.0f ) > 0.01f ) ) {
// check whether we need to enable normal vectors normalization for this submodel
ErrorLog( "Bad model: transformation matrix for sub-model \"" + pName + "\" imposes geometry scaling (factor: " + to_string( Det( *fMatrix ), 2 ) + ")" );
m_normalizenormals = true;
}
}; };
void TModel3d::LoadFromBinFile(std::string const &FileName, bool dynamic) void TModel3d::LoadFromBinFile(std::string const &FileName, bool dynamic)

View File

@@ -96,6 +96,7 @@ private:
f4Diffuse { 1.0f,1.0f,1.0f,1.0f }, f4Diffuse { 1.0f,1.0f,1.0f,1.0f },
f4Specular { 0.0f,0.0f,0.0f,1.0f }, f4Specular { 0.0f,0.0f,0.0f,1.0f },
f4Emision { 1.0f,1.0f,1.0f,1.0f }; f4Emision { 1.0f,1.0f,1.0f,1.0f };
bool m_normalizenormals { false }; // indicates vectors need to be normalized due to scaling etc
float fWireSize { 0.0f }; // nie używane, ale wczytywane float fWireSize { 0.0f }; // nie używane, ale wczytywane
float fSquareMaxDist { 10000.0f * 10000.0f }; float fSquareMaxDist { 10000.0f * 10000.0f };
float fSquareMinDist { 0.0f }; float fSquareMinDist { 0.0f };

View File

@@ -2277,34 +2277,34 @@ world_environment::update() {
auto const moonlightlevel = m_moon.getIntensity() * 0.65f; // scaled down by arbitrary factor, it's pretty bright otherwise auto const moonlightlevel = m_moon.getIntensity() * 0.65f; // scaled down by arbitrary factor, it's pretty bright otherwise
float keylightintensity; float keylightintensity;
float twilightfactor; float twilightfactor;
float3 keylightcolor; glm::vec3 keylightcolor;
if( moonlightlevel > sunlightlevel ) { if( moonlightlevel > sunlightlevel ) {
// rare situations when the moon is brighter than the sun, typically at night // rare situations when the moon is brighter than the sun, typically at night
Global::SunAngle = m_moon.getAngle(); Global::SunAngle = m_moon.getAngle();
Global::DayLight.set_position( m_moon.getPosition() ); Global::DayLight.set_position( m_moon.getPosition() );
Global::DayLight.direction = -1.0 * m_moon.getDirection(); Global::DayLight.direction = -1.0f * m_moon.getDirection();
keylightintensity = moonlightlevel; keylightintensity = moonlightlevel;
// if the moon is up, it overrides the twilight // if the moon is up, it overrides the twilight
twilightfactor = 0.0f; twilightfactor = 0.0f;
keylightcolor = float3( 255.0f / 255.0f, 242.0f / 255.0f, 202.0f / 255.0f ); keylightcolor = glm::vec3( 255.0f / 255.0f, 242.0f / 255.0f, 202.0f / 255.0f );
} }
else { else {
// regular situation with sun as the key light // regular situation with sun as the key light
Global::SunAngle = m_sun.getAngle(); Global::SunAngle = m_sun.getAngle();
Global::DayLight.set_position( m_sun.getPosition() ); Global::DayLight.set_position( m_sun.getPosition() );
Global::DayLight.direction = -1.0 * m_sun.getDirection(); Global::DayLight.direction = -1.0f * m_sun.getDirection();
keylightintensity = sunlightlevel; keylightintensity = sunlightlevel;
// diffuse (sun) intensity goes down after twilight, and reaches minimum 18 degrees below horizon // diffuse (sun) intensity goes down after twilight, and reaches minimum 18 degrees below horizon
twilightfactor = clamp( -Global::SunAngle, 0.0f, 18.0f ) / 18.0f; twilightfactor = clamp( -Global::SunAngle, 0.0f, 18.0f ) / 18.0f;
float const duskfactor = 1.0f - clamp( Global::SunAngle, 0.0f, 18.0f ) / 18.0f; float const duskfactor = 1.0f - clamp( Global::SunAngle, 0.0f, 18.0f ) / 18.0f;
keylightcolor = interpolate( keylightcolor = interpolate(
float3( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f ), glm::vec3( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f ),
float3( 235.0f / 255.0f, 140.0f / 255.0f, 36.0f / 255.0f ), glm::vec3( 235.0f / 255.0f, 140.0f / 255.0f, 36.0f / 255.0f ),
duskfactor ); duskfactor );
} }
// ...update skydome to match the current sun position as well... // ...update skydome to match the current sun position as well...
m_skydome.SetOvercastFactor( Global::Overcast ); m_skydome.SetOvercastFactor( Global::Overcast );
m_skydome.Update( m_sun.getPosition() ); m_skydome.Update( m_sun.getDirection() );
// ...retrieve current sky colour and brightness... // ...retrieve current sky colour and brightness...
auto const skydomecolour = m_skydome.GetAverageColor(); auto const skydomecolour = m_skydome.GetAverageColor();
auto const skydomehsv = RGBtoHSV( skydomecolour ); auto const skydomehsv = RGBtoHSV( skydomecolour );
@@ -2319,9 +2319,8 @@ world_environment::update() {
auto const diffuselevel = interpolate( keylightintensity, intensity * ( 1.0f - twilightfactor ), 1.0f - Global::Overcast * 0.75f ); auto const diffuselevel = interpolate( keylightintensity, intensity * ( 1.0f - twilightfactor ), 1.0f - Global::Overcast * 0.75f );
// ...update light colours and intensity. // ...update light colours and intensity.
keylightcolor = keylightcolor * diffuselevel; keylightcolor = keylightcolor * diffuselevel;
Global::DayLight.diffuse[ 0 ] = keylightcolor.x; Global::DayLight.diffuse = glm::vec4( keylightcolor, Global::DayLight.diffuse.a );
Global::DayLight.diffuse[ 1 ] = keylightcolor.y; Global::DayLight.specular = glm::vec4( keylightcolor * 0.85f, diffuselevel );
Global::DayLight.diffuse[ 2 ] = keylightcolor.z;
// tonal impact of skydome color is inversely proportional to how high the sun is above the horizon // tonal impact of skydome color is inversely proportional to how high the sun is above the horizon
// (this is pure conjecture, aimed more to 'look right' than be accurate) // (this is pure conjecture, aimed more to 'look right' than be accurate)

74
color.h
View File

@@ -3,28 +3,28 @@
#include "float3d.h" #include "float3d.h"
inline inline
float3 glm::vec3
XYZtoRGB( float3 const &XYZ ) { XYZtoRGB( glm::vec3 const &XYZ ) {
// M^-1 for Adobe RGB from http://www.brucelindbloom.com/Eqn_RGB_XYZ_Matrix.html // M^-1 for Adobe RGB from http://www.brucelindbloom.com/Eqn_RGB_XYZ_Matrix.html
float const mi[ 3 ][ 3 ] = { 2.041369f, -0.969266f, 0.0134474f, -0.5649464f, 1.8760108f, -0.1183897f, -0.3446944f, 0.041556f, 1.0154096f }; float const mi[ 3 ][ 3 ] = { 2.041369f, -0.969266f, 0.0134474f, -0.5649464f, 1.8760108f, -0.1183897f, -0.3446944f, 0.041556f, 1.0154096f };
// m^-1 for sRGB: // m^-1 for sRGB:
// float const mi[ 3 ][ 3 ] = { 3.240479f, -0.969256f, 0.055648f, -1.53715f, 1.875991f, -0.204043f, -0.49853f, 0.041556f, 1.057311f }; // float const mi[ 3 ][ 3 ] = { 3.240479f, -0.969256f, 0.055648f, -1.53715f, 1.875991f, -0.204043f, -0.49853f, 0.041556f, 1.057311f };
return float3{ return glm::vec3{
XYZ.x*mi[ 0 ][ 0 ] + XYZ.y*mi[ 1 ][ 0 ] + XYZ.z*mi[ 2 ][ 0 ], XYZ.x*mi[ 0 ][ 0 ] + XYZ.y*mi[ 1 ][ 0 ] + XYZ.z*mi[ 2 ][ 0 ],
XYZ.x*mi[ 0 ][ 1 ] + XYZ.y*mi[ 1 ][ 1 ] + XYZ.z*mi[ 2 ][ 1 ], XYZ.x*mi[ 0 ][ 1 ] + XYZ.y*mi[ 1 ][ 1 ] + XYZ.z*mi[ 2 ][ 1 ],
XYZ.x*mi[ 0 ][ 2 ] + XYZ.y*mi[ 1 ][ 2 ] + XYZ.z*mi[ 2 ][ 2 ] }; XYZ.x*mi[ 0 ][ 2 ] + XYZ.y*mi[ 1 ][ 2 ] + XYZ.z*mi[ 2 ][ 2 ] };
} }
inline inline
float3 glm::vec3
RGBtoHSV( float3 const &RGB ) { RGBtoHSV( glm::vec3 const &RGB ) {
float3 hsv; glm::vec3 hsv;
float const max = std::max( std::max( RGB.x, RGB.y ), RGB.z ); float const max = std::max( std::max( RGB.r, RGB.g ), RGB.b );
float const min = std::min( std::min( RGB.x, RGB.y ), RGB.z ); float const min = std::min( std::min( RGB.r, RGB.g ), RGB.b );
float const delta = max - min; float const delta = max - min;
hsv.z = max; // v hsv.z = max; // v
@@ -43,13 +43,13 @@ RGBtoHSV( float3 const &RGB ) {
hsv.x = NAN; // its now undefined hsv.x = NAN; // its now undefined
return hsv; return hsv;
} }
if( RGB.x >= max ) // > is bogus, just keeps compilor happy if( RGB.r >= max ) // > is bogus, just keeps compilor happy
hsv.x = ( RGB.y - RGB.z ) / delta; // between yellow & magenta hsv.x = ( RGB.g - RGB.b ) / delta; // between yellow & magenta
else else
if( RGB.y >= max ) if( RGB.g >= max )
hsv.x = 2.0 + ( RGB.y - RGB.x ) / delta; // between cyan & yellow hsv.x = 2.0 + ( RGB.g - RGB.r ) / delta; // between cyan & yellow
else else
hsv.x = 4.0 + ( RGB.x - RGB.y ) / delta; // between magenta & cyan hsv.x = 4.0 + ( RGB.r - RGB.g ) / delta; // between magenta & cyan
hsv.x *= 60.0; // degrees hsv.x *= 60.0; // degrees
@@ -60,15 +60,15 @@ RGBtoHSV( float3 const &RGB ) {
} }
inline inline
float3 glm::vec3
HSVtoRGB( float3 const &HSV ) { HSVtoRGB( glm::vec3 const &HSV ) {
float3 rgb; glm::vec3 rgb;
if( HSV.y <= 0.0 ) { // < is bogus, just shuts up warnings if( HSV.y <= 0.0 ) { // < is bogus, just shuts up warnings
rgb.x = HSV.z; rgb.r = HSV.z;
rgb.y = HSV.z; rgb.g = HSV.z;
rgb.z = HSV.z; rgb.b = HSV.z;
return rgb; return rgb;
} }
float hh = HSV.x; float hh = HSV.x;
@@ -82,36 +82,36 @@ HSVtoRGB( float3 const &HSV ) {
switch( i ) { switch( i ) {
case 0: case 0:
rgb.x = HSV.z; rgb.r = HSV.z;
rgb.y = t; rgb.g = t;
rgb.z = p; rgb.b = p;
break; break;
case 1: case 1:
rgb.x = q; rgb.r = q;
rgb.y = HSV.z; rgb.g = HSV.z;
rgb.z = p; rgb.b = p;
break; break;
case 2: case 2:
rgb.x = p; rgb.r = p;
rgb.y = HSV.z; rgb.g = HSV.z;
rgb.z = t; rgb.b = t;
break; break;
case 3: case 3:
rgb.x = p; rgb.r = p;
rgb.y = q; rgb.g = q;
rgb.z = HSV.z; rgb.b = HSV.z;
break; break;
case 4: case 4:
rgb.x = t; rgb.r = t;
rgb.y = p; rgb.g = p;
rgb.z = HSV.z; rgb.b = HSV.z;
break; break;
case 5: case 5:
default: default:
rgb.x = HSV.z; rgb.r = HSV.z;
rgb.y = p; rgb.g = p;
rgb.z = q; rgb.b = q;
break; break;
} }
return rgb; return rgb;

View File

@@ -47,12 +47,12 @@ light_array::update() {
if( light.index == 0 ) { if( light.index == 0 ) {
// front light set // front light set
light.position = light.owner->GetPosition() + ( light.owner->VectorFront() * light.owner->GetLength() * 0.4 ); light.position = light.owner->GetPosition() + ( light.owner->VectorFront() * light.owner->GetLength() * 0.4 );
light.direction = light.owner->VectorFront(); light.direction = glm::make_vec3( light.owner->VectorFront().getArray() );
} }
else { else {
// rear light set // rear light set
light.position = light.owner->GetPosition() - ( light.owner->VectorFront() * light.owner->GetLength() * 0.4 ); light.position = light.owner->GetPosition() - ( light.owner->VectorFront() * light.owner->GetLength() * 0.4 );
light.direction = light.owner->VectorFront(); light.direction = glm::make_vec3( light.owner->VectorFront().getArray() );
light.direction.x = -light.direction.x; light.direction.x = -light.direction.x;
light.direction.z = -light.direction.z; light.direction.z = -light.direction.z;
} }

View File

@@ -20,7 +20,7 @@ public:
TDynamicObject const *owner; // the object in world which 'carries' the light TDynamicObject const *owner; // the object in world which 'carries' the light
int index{ -1 }; // 0: front lights, 1: rear lights int index{ -1 }; // 0: front lights, 1: rear lights
Math3D::vector3 position; // position of the light in 3d scene Math3D::vector3 position; // position of the light in 3d scene
Math3D::vector3 direction; // direction of the light in 3d scene glm::vec3 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 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) float intensity{ 0.0f }; // (combined) intensity of the light(s)
int count{ 0 }; // number (or pattern) of active light(s) int count{ 0 }; // number (or pattern) of active light(s)

View File

@@ -36,9 +36,9 @@ void
cMoon::update() { cMoon::update() {
move(); move();
Math3D::vector3 position( 0.0f, 0.0f, -2000.0f * Global::fDistanceFactor ); glm::vec3 position( 0.0f, 0.0f, -2000.0f * Global::fDistanceFactor );
position.RotateX( (float)( m_body.elevref * ( M_PI / 180.0 ) ) ); position = glm::rotateX( position, (float)( m_body.elevref * ( M_PI / 180.0 ) ) );
position.RotateY( (float)( -m_body.hrang * ( M_PI / 180.0 ) ) ); position = glm::rotateY( position, (float)( -m_body.hrang * ( M_PI / 180.0 ) ) );
m_position = position; m_position = position;
} }
@@ -59,14 +59,10 @@ cMoon::render() {
glPopMatrix(); glPopMatrix();
} }
Math3D::vector3 glm::vec3
cMoon::getDirection() { cMoon::getDirection() {
Math3D::vector3 position( 0.f, 0.f, -1.f ); return glm::normalize( m_position );
position.RotateX( (float)( m_body.elevref * (M_PI/180.0)) );
position.RotateY( (float)( -m_body.hrang * (M_PI/180.0)) );
position.Normalize();
return position;
} }
float float

7
moon.h
View File

@@ -3,7 +3,6 @@
#include "windows.h" #include "windows.h"
#include "GL/glew.h" #include "GL/glew.h"
#include "GL/wglew.h" #include "GL/wglew.h"
#include "dumb3d.h"
// TODO: sun and moon share code as celestial bodies, we could make a base class out of it // TODO: sun and moon share code as celestial bodies, we could make a base class out of it
@@ -18,9 +17,9 @@ public:
void update(); void update();
void render(); void render();
// returns location of the sun in the 3d scene // returns location of the sun in the 3d scene
Math3D::vector3 getPosition() { return m_position; } glm::vec3 getPosition() { return m_position; }
// returns vector pointing at the sun // returns vector pointing at the sun
Math3D::vector3 getDirection(); glm::vec3 getDirection();
// returns current elevation above horizon // returns current elevation above horizon
float getAngle() const; float getAngle() const;
// returns current intensity of the sun // returns current intensity of the sun
@@ -101,6 +100,6 @@ protected:
celestialbody m_body; celestialbody m_body;
observer m_observer; observer m_observer;
Math3D::vector3 m_position; glm::vec3 m_position;
float m_phase; float m_phase;
}; };

View File

@@ -50,8 +50,13 @@ cParser::cParser( std::string const &Stream, buffertype const Type, std::string
// calculate stream size // calculate stream size
if (mStream) if (mStream)
{ {
mSize = mStream->rdbuf()->pubseekoff(0, std::ios_base::end); if( true == mStream->fail() ) {
mStream->rdbuf()->pubseekoff(0, std::ios_base::beg); ErrorLog( "Failed to open file \"" + Path + "\"" );
}
else {
mSize = mStream->rdbuf()->pubseekoff( 0, std::ios_base::end );
mStream->rdbuf()->pubseekoff( 0, std::ios_base::beg );
}
} }
else else
mSize = 0; mSize = 0;

View File

@@ -24,6 +24,12 @@ http://mozilla.org/MPL/2.0/.
opengl_renderer GfxRenderer; opengl_renderer GfxRenderer;
extern TWorld World; extern TWorld World;
namespace colors {
glm::vec4 const none { 0.0f, 0.0f, 0.0f, 1.0f };
} // namespace colors
// returns true if specified object is within camera frustum, false otherwise // returns true if specified object is within camera frustum, false otherwise
bool bool
opengl_camera::visible( bounding_area const &Area ) const { opengl_camera::visible( bounding_area const &Area ) const {
@@ -74,14 +80,19 @@ opengl_renderer::Init( GLFWwindow *Window ) {
glPointSize( 3.0f ); glPointSize( 3.0f );
glEnable( GL_POINT_SMOOTH ); glEnable( GL_POINT_SMOOTH );
glEnable( GL_COLOR_MATERIAL ); ::glLightModeli( GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR );
glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE ); ::glMaterialf( GL_FRONT, GL_SHININESS, 15.0f );
if( true == Global::ScaleSpecularValues ) {
m_specularopaquescalefactor = 0.25f;
m_speculartranslucentscalefactor = 1.5f;
}
::glEnable( GL_COLOR_MATERIAL );
::glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
// setup lighting // setup lighting
GLfloat ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f }; ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr(m_baseambient) );
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient ); ::glEnable( GL_LIGHTING );
glEnable( GL_LIGHTING ); ::glEnable( GL_LIGHT0 );
glEnable( GL_LIGHT0 );
Global::DayLight.id = opengl_renderer::sunlight; Global::DayLight.id = opengl_renderer::sunlight;
// directional light // directional light
@@ -205,9 +216,9 @@ opengl_renderer::Render( world_environment *Environment ) {
Environment->m_stars.render(); Environment->m_stars.render();
float const duskfactor = 1.0f - clamp( std::abs( Environment->m_sun.getAngle() ), 0.0f, 12.0f ) / 12.0f; float const duskfactor = 1.0f - clamp( std::abs( Environment->m_sun.getAngle() ), 0.0f, 12.0f ) / 12.0f;
float3 suncolor = interpolate( glm::vec3 suncolor = interpolate(
float3( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f ), glm::vec3( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f ),
float3( 235.0f / 255.0f, 140.0f / 255.0f, 36.0f / 255.0f ), glm::vec3( 235.0f / 255.0f, 140.0f / 255.0f, 36.0f / 255.0f ),
duskfactor ); duskfactor );
if( DebugModeFlag == true ) { if( DebugModeFlag == true ) {
@@ -248,11 +259,10 @@ opengl_renderer::Render( world_environment *Environment ) {
// moon // moon
{ {
Bind( m_moontexture ); Bind( m_moontexture );
float3 mooncolor( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f ); glm::vec3 mooncolor( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f );
::glColor4f( mooncolor.x, mooncolor.y, mooncolor.z, static_cast<GLfloat>( 1.0 - Global::fLuminance * 0.5 ) ); ::glColor4f( mooncolor.x, mooncolor.y, mooncolor.z, static_cast<GLfloat>( 1.0 - Global::fLuminance * 0.5 ) );
auto const moonvector = Environment->m_moon.getDirection(); auto const moonposition = modelview * glm::vec4( Environment->m_moon.getDirection(), 1.0f );
auto const moonposition = modelview * glm::vec4( moonvector.x, moonvector.y, moonvector.z, 1.0f );
::glPushMatrix(); ::glPushMatrix();
::glLoadIdentity(); // macierz jedynkowa ::glLoadIdentity(); // macierz jedynkowa
::glTranslatef( moonposition.x, moonposition.y, moonposition.z ); ::glTranslatef( moonposition.x, moonposition.y, moonposition.z );
@@ -553,7 +563,7 @@ opengl_renderer::Render( TGroundNode *Node ) {
::glColor4fv( ::glColor4fv(
glm::value_ptr( glm::value_ptr(
glm::vec4( glm::vec4(
Node->Diffuse * glm::make_vec3( Global::DayLight.ambient ), // w zaleznosci od koloru swiatla Node->Diffuse * glm::vec3( Global::DayLight.ambient ), // w zaleznosci od koloru swiatla
1.0 ) ) ); // if the thickness is defined negative, lines are always drawn opaque 1.0 ) ) ); // if the thickness is defined negative, lines are always drawn opaque
auto const linewidth = clamp( 0.5 * linealpha + Node->fLineThickness * Node->m_radius / 1000.0, 1.0, 32.0 ); auto const linewidth = clamp( 0.5 * linealpha + Node->fLineThickness * Node->m_radius / 1000.0, 1.0, 32.0 );
if( linewidth > 1.0 ) { if( linewidth > 1.0 ) {
@@ -633,6 +643,7 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
// change light level based on light level of the occupied track // change light level based on light level of the occupied track
Global::DayLight.apply_intensity( Dynamic->fShade ); Global::DayLight.apply_intensity( Dynamic->fShade );
} }
m_renderspecular = true; // vehicles are rendered with specular component. static models without, at least for the time being
// render // render
if( Dynamic->mdLowPolyInt ) { if( Dynamic->mdLowPolyInt ) {
@@ -650,18 +661,19 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
if( Dynamic->InteriorLightLevel > 0.0f ) { if( Dynamic->InteriorLightLevel > 0.0f ) {
// reset the overall ambient // reset the overall ambient
GLfloat ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f }; ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr(m_baseambient) );
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient );
} }
} }
} }
Render( Dynamic->mdModel, Dynamic->Material(), squaredistance ); if( Dynamic->mdModel )
Render( Dynamic->mdModel, Dynamic->Material(), squaredistance );
if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance ); Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance );
// post-render cleanup // post-render cleanup
m_renderspecular = false;
if( Dynamic->fShade > 0.0f ) { if( Dynamic->fShade > 0.0f ) {
// restore regular light level // restore regular light level
Global::DayLight.apply_intensity(); Global::DayLight.apply_intensity();
@@ -746,6 +758,9 @@ opengl_renderer::Render( TSubModel *Submodel ) {
// renderowanie obiektów OpenGL // renderowanie obiektów OpenGL
if( Submodel->iAlpha & Submodel->iFlags & 0x1F ) // rysuj gdy element nieprzezroczysty if( Submodel->iAlpha & Submodel->iFlags & 0x1F ) // rysuj gdy element nieprzezroczysty
{ {
if( true == Submodel->m_normalizenormals ) {
::glEnable( GL_NORMALIZE );
}
// material configuration: // material configuration:
// textures... // textures...
if( Submodel->TextureID < 0 ) if( Submodel->TextureID < 0 )
@@ -756,7 +771,12 @@ opengl_renderer::Render( TSubModel *Submodel ) {
// również 0 // również 0
Bind( Submodel->TextureID ); Bind( Submodel->TextureID );
} }
// ...colors...
::glColor3fv( glm::value_ptr(Submodel->f4Diffuse) ); // McZapkie-240702: zamiast ub ::glColor3fv( glm::value_ptr(Submodel->f4Diffuse) ); // McZapkie-240702: zamiast ub
if( ( true == m_renderspecular ) && ( Global::DayLight.specular.a > 0.01f ) ) {
// specular strength in legacy models is set uniformly to 150, 150, 150 so we scale it down for opaque elements
::glMaterialfv( GL_FRONT, GL_SPECULAR, glm::value_ptr( Submodel->f4Specular * Global::DayLight.specular.a * m_specularopaquescalefactor ) );
}
// ...luminance // ...luminance
if( Global::fLuminance < Submodel->fLight ) { if( Global::fLuminance < Submodel->fLight ) {
// zeby swiecilo na kolorowo // zeby swiecilo na kolorowo
@@ -767,10 +787,15 @@ opengl_renderer::Render( TSubModel *Submodel ) {
m_geometry.draw( Submodel->m_geometry ); m_geometry.draw( Submodel->m_geometry );
// post-draw reset // post-draw reset
if( ( true == m_renderspecular ) && ( Global::DayLight.specular.a > 0.01f ) ) {
::glMaterialfv( GL_FRONT, GL_SPECULAR, glm::value_ptr( colors::none ) );
}
if( Global::fLuminance < Submodel->fLight ) { if( Global::fLuminance < Submodel->fLight ) {
// restore default (lack of) brightness // restore default (lack of) brightness
glm::vec4 const noemission( 0.0f, 0.0f, 0.0f, 1.0f ); ::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( colors::none ) );
::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( noemission ) ); }
if( true == Submodel->m_normalizenormals ) {
::glDisable( GL_NORMALIZE );
} }
} }
} }
@@ -1006,7 +1031,7 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
::glColor4fv( ::glColor4fv(
glm::value_ptr( glm::value_ptr(
glm::vec4( glm::vec4(
Node->Diffuse * glm::make_vec3( Global::DayLight.ambient ), // w zaleznosci od koloru swiatla Node->Diffuse * glm::vec3( Global::DayLight.ambient ), // w zaleznosci od koloru swiatla
std::min( 1.0, linealpha ) ) ) ); std::min( 1.0, linealpha ) ) ) );
auto const linewidth = clamp( 0.5 * linealpha + Node->fLineThickness * Node->m_radius / 1000.0, 1.0, 32.0 ); auto const linewidth = clamp( 0.5 * linealpha + Node->fLineThickness * Node->m_radius / 1000.0, 1.0, 32.0 );
if( linewidth > 1.0 ) { if( linewidth > 1.0 ) {
@@ -1078,6 +1103,7 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
// change light level based on light level of the occupied track // change light level based on light level of the occupied track
Global::DayLight.apply_intensity( Dynamic->fShade ); Global::DayLight.apply_intensity( Dynamic->fShade );
} }
m_renderspecular = true;
// render // render
if( Dynamic->mdLowPolyInt ) { if( Dynamic->mdLowPolyInt ) {
@@ -1095,18 +1121,19 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
if( Dynamic->InteriorLightLevel > 0.0f ) { if( Dynamic->InteriorLightLevel > 0.0f ) {
// reset the overall ambient // reset the overall ambient
GLfloat ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f }; ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( m_baseambient ) );
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient );
} }
} }
} }
Render_Alpha( Dynamic->mdModel, Dynamic->Material(), squaredistance ); if( Dynamic->mdModel )
Render_Alpha( Dynamic->mdModel, Dynamic->Material(), squaredistance );
if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku
Render_Alpha( Dynamic->mdLoad, Dynamic->Material(), squaredistance ); Render_Alpha( Dynamic->mdLoad, Dynamic->Material(), squaredistance );
// post-render cleanup // post-render cleanup
m_renderspecular = false;
if( Dynamic->fShade > 0.0f ) { if( Dynamic->fShade > 0.0f ) {
// restore regular light level // restore regular light level
Global::DayLight.apply_intensity(); Global::DayLight.apply_intensity();
@@ -1190,6 +1217,9 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
// renderowanie obiektów OpenGL // renderowanie obiektów OpenGL
if( Submodel->iAlpha & Submodel->iFlags & 0x2F ) // rysuj gdy element przezroczysty if( Submodel->iAlpha & Submodel->iFlags & 0x2F ) // rysuj gdy element przezroczysty
{ {
if( true == Submodel->m_normalizenormals ) {
::glEnable( GL_NORMALIZE );
}
// textures... // textures...
if( Submodel->TextureID < 0 ) { // zmienialne skóry if( Submodel->TextureID < 0 ) { // zmienialne skóry
Bind( Submodel->ReplacableSkinId[ -Submodel->TextureID ] ); Bind( Submodel->ReplacableSkinId[ -Submodel->TextureID ] );
@@ -1198,7 +1228,11 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
// również 0 // również 0
Bind( Submodel->TextureID ); Bind( Submodel->TextureID );
} }
// ...colors...
::glColor3fv( glm::value_ptr(Submodel->f4Diffuse) ); // McZapkie-240702: zamiast ub ::glColor3fv( glm::value_ptr(Submodel->f4Diffuse) ); // McZapkie-240702: zamiast ub
if( ( true == m_renderspecular ) && ( Global::DayLight.specular.a > 0.01f ) ) {
::glMaterialfv( GL_FRONT, GL_SPECULAR, glm::value_ptr( Submodel->f4Specular * Global::DayLight.specular.a * m_speculartranslucentscalefactor ) );
}
// ...luminance // ...luminance
if( Global::fLuminance < Submodel->fLight ) { if( Global::fLuminance < Submodel->fLight ) {
// zeby swiecilo na kolorowo // zeby swiecilo na kolorowo
@@ -1209,10 +1243,15 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
m_geometry.draw( Submodel->m_geometry ); m_geometry.draw( Submodel->m_geometry );
// post-draw reset // post-draw reset
if( ( true == m_renderspecular ) && ( Global::DayLight.specular.a > 0.01f ) ) {
::glMaterialfv( GL_FRONT, GL_SPECULAR, glm::value_ptr( colors::none ) );
}
if( Global::fLuminance < Submodel->fLight ) { if( Global::fLuminance < Submodel->fLight ) {
// restore default (lack of) brightness // restore default (lack of) brightness
glm::vec4 const noemission( 0.0f, 0.0f, 0.0f, 1.0f ); ::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( colors::none ) );
::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( noemission ) ); }
if( true == Submodel->m_normalizenormals ) {
::glDisable( GL_NORMALIZE );
} }
} }
} }
@@ -1399,7 +1438,7 @@ opengl_renderer::Update_Lights( light_array const &Lights ) {
continue; continue;
} }
// if the light passed tests so far, it's good enough // if the light passed tests so far, it's good enough
renderlight->set_position( scenelight.position - Global::pCameraPosition ); renderlight->set_position( glm::make_vec3( (scenelight.position - Global::pCameraPosition).readArray() ) );
renderlight->direction = scenelight.direction; renderlight->direction = scenelight.direction;
auto luminance = Global::fLuminance; // TODO: adjust this based on location, e.g. for tunnels auto luminance = Global::fLuminance; // TODO: adjust this based on location, e.g. for tunnels

View File

@@ -21,53 +21,44 @@ http://mozilla.org/MPL/2.0/.
struct opengl_light { struct opengl_light {
GLuint id{ (GLuint)-1 }; GLuint id{ (GLuint)-1 };
Math3D::vector3 direction; glm::vec3 direction;
GLfloat position[ 4 ]; // 4th parameter specifies directional(0) or omni-directional(1) light source glm::vec4
GLfloat ambient[ 4 ]; position { 0.0f, 0.0f, 0.0f, 1.0f }, // 4th parameter specifies directional(0) or omni-directional(1) light source
GLfloat diffuse[ 4 ]; ambient { 0.0f, 0.0f, 0.0f, 1.0f },
GLfloat specular[ 4 ]; diffuse { 1.0f, 1.0f, 1.0f, 1.0f },
specular { 1.0f, 1.0f, 1.0f, 1.0f };
opengl_light() {
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 inline
void apply_intensity( float const Factor = 1.0f ) { void apply_intensity( float const Factor = 1.0f ) {
if( Factor == 1.0 ) { if( Factor == 1.0 ) {
glLightfv( id, GL_AMBIENT, ambient ); glLightfv( id, GL_AMBIENT, glm::value_ptr(ambient) );
glLightfv( id, GL_DIFFUSE, diffuse ); glLightfv( id, GL_DIFFUSE, glm::value_ptr(diffuse) );
glLightfv( id, GL_SPECULAR, specular ); glLightfv( id, GL_SPECULAR, glm::value_ptr(specular) );
} }
else { else {
// temporary light scaling mechanics (ultimately this work will be left to the shaders // temporary light scaling mechanics (ultimately this work will be left to the shaders
float4 scaledambient( ambient[ 0 ] * Factor, ambient[ 1 ] * Factor, ambient[ 2 ] * Factor, ambient[ 3 ] ); glm::vec4 scaledambient( ambient.r * Factor, ambient.g * Factor, ambient.b * Factor, ambient.a );
float4 scaleddiffuse( diffuse[ 0 ] * Factor, diffuse[ 1 ] * Factor, diffuse[ 2 ] * Factor, diffuse[ 3 ] ); glm::vec4 scaleddiffuse( diffuse.r * Factor, diffuse.g * Factor, diffuse.b * Factor, diffuse.a );
float4 scaledspecular( specular[ 0 ] * Factor, specular[ 1 ] * Factor, specular[ 2 ] * Factor, specular[ 3 ] ); glm::vec4 scaledspecular( specular.r * Factor, specular.g * Factor, specular.b * Factor, specular.a );
glLightfv( id, GL_AMBIENT, &scaledambient.x ); glLightfv( id, GL_AMBIENT, glm::value_ptr(scaledambient) );
glLightfv( id, GL_DIFFUSE, &scaleddiffuse.x ); glLightfv( id, GL_DIFFUSE, glm::value_ptr(scaleddiffuse) );
glLightfv( id, GL_SPECULAR, &scaledspecular.x ); glLightfv( id, GL_SPECULAR, glm::value_ptr(scaledspecular) );
} }
} }
inline inline
void apply_angle() { void apply_angle() {
glLightfv( id, GL_POSITION, position ); glLightfv( id, GL_POSITION, glm::value_ptr(position) );
if( position[ 3 ] == 1.0f ) { if( position.w == 1.0f ) {
GLfloat directionarray[] = { (GLfloat)direction.x, (GLfloat)direction.y, (GLfloat)direction.z }; glLightfv( id, GL_SPOT_DIRECTION, glm::value_ptr(direction) );
glLightfv( id, GL_SPOT_DIRECTION, directionarray );
} }
} }
inline inline
void set_position( Math3D::vector3 const &Position ) { void set_position( glm::vec3 const &Position ) {
position[ 0 ] = Position.x; position = glm::vec4( Position, position.w );
position[ 1 ] = Position.y;
position[ 2 ] = Position.z;
} }
}; };
@@ -229,6 +220,10 @@ private:
geometry_handle m_billboardgeometry { 0, 0 }; geometry_handle m_billboardgeometry { 0, 0 };
GLUquadricObj *m_quadric; // helper object for drawing debug mode scene elements GLUquadricObj *m_quadric; // helper object for drawing debug mode scene elements
std::vector<distancesubcell_pair> m_drawqueue; // list of subcells to be drawn in current render pass std::vector<distancesubcell_pair> m_drawqueue; // list of subcells to be drawn in current render pass
glm::vec4 m_baseambient { 0.0f, 0.0f, 0.0f, 1.0f };
bool m_renderspecular{ false }; // controls whether to include specular component in the calculations
float m_specularopaquescalefactor { 1.0f };
float m_speculartranslucentscalefactor { 1.0f };
}; };

View File

@@ -27,14 +27,14 @@ void TSky::Init()
mdCloud = TModelsManager::GetModel( Global::asSky ); mdCloud = TModelsManager::GetModel( Global::asSky );
}; };
void TSky::Render( float3 const &Tint ) void TSky::Render( glm::vec3 const &Tint )
{ {
if (mdCloud) if (mdCloud)
{ // jeśli jest model nieba { // jeśli jest model nieba
// setup // setup
::glEnable( GL_LIGHTING ); ::glEnable( GL_LIGHTING );
GfxRenderer.Disable_Lights(); GfxRenderer.Disable_Lights();
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, &Tint.x ); ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr(Tint) );
// render // render
GfxRenderer.Render( mdCloud, nullptr, 100.0 ); GfxRenderer.Render( mdCloud, nullptr, 100.0 );
GfxRenderer.Render_Alpha( mdCloud, nullptr, 100.0 ); GfxRenderer.Render_Alpha( mdCloud, nullptr, 100.0 );

3
sky.h
View File

@@ -11,7 +11,6 @@ http://mozilla.org/MPL/2.0/.
#pragma once #pragma once
#include "Model3d.h" #include "Model3d.h"
#include "Float3d.h"
class TSky class TSky
{ {
@@ -22,7 +21,7 @@ class TSky
TSky(); TSky();
~TSky(); ~TSky();
void Init(); void Init();
void Render( float3 const &Tint = float3(1.0f, 1.0f, 1.0f) ); void Render( glm::vec3 const &Tint = glm::vec3(1.0f, 1.0f, 1.0f) );
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -86,8 +86,8 @@ void CSkyDome::Generate() {
// m_normals.emplace_back( float3( x * zr, -y * zr, -z ) ); // m_normals.emplace_back( float3( x * zr, -y * zr, -z ) );
*/ */
// cartesian to opengl swap: -x, -z, -y // cartesian to opengl swap: -x, -z, -y
m_vertices.emplace_back( float3( -x * zr, -z - offset, -y * zr ) * radius ); m_vertices.emplace_back( glm::vec3( -x * zr, -z - offset, -y * zr ) * radius );
m_colours.emplace_back( float3( 0.75f, 0.75f, 0.75f ) ); // placeholder m_colours.emplace_back( glm::vec3( 0.75f, 0.75f, 0.75f ) ); // placeholder
if( (i == 0) || (j == 0) ) { if( (i == 0) || (j == 0) ) {
// initial edge of the dome, don't start indices yet // initial edge of the dome, don't start indices yet
@@ -107,7 +107,7 @@ void CSkyDome::Generate() {
} }
} }
void CSkyDome::Update( Math3D::vector3 const &Sun ) { void CSkyDome::Update( glm::vec3 const &Sun ) {
if( true == SetSunPosition( Sun ) ) { if( true == SetSunPosition( Sun ) ) {
// build colors if there's a change in sun position // build colors if there's a change in sun position
@@ -150,15 +150,14 @@ void CSkyDome::Render() {
::glDisableClientState( GL_VERTEX_ARRAY ); ::glDisableClientState( GL_VERTEX_ARRAY );
} }
bool CSkyDome::SetSunPosition( Math3D::vector3 const &Direction ) { bool CSkyDome::SetSunPosition( glm::vec3 const &Direction ) {
auto sundirection = SafeNormalize( float3( Direction.x, Direction.y, Direction.z) ); if( Direction == m_sundirection ) {
if( sundirection == m_sundirection ) {
return false; return false;
} }
m_sundirection = sundirection; m_sundirection = Direction;
m_thetasun = std::acosf( m_sundirection.y ); m_thetasun = std::acosf( m_sundirection.y );
m_phisun = std::atan2( m_sundirection.z, m_sundirection.x ); m_phisun = std::atan2( m_sundirection.z, m_sundirection.x );
@@ -244,18 +243,18 @@ void CSkyDome::RebuildColors() {
zenithluminance = PerezFunctionO1( perezluminance, m_thetasun, zenithluminance ); zenithluminance = PerezFunctionO1( perezluminance, m_thetasun, zenithluminance );
// start with fresh average for the new pass // start with fresh average for the new pass
float3 averagecolor{ 0.0f, 0.0f, 0.0f }; glm::vec3 averagecolor { 0.0f, 0.0f, 0.0f };
// trough all vertices // trough all vertices
float3 vertex; glm::vec3 vertex;
float3 color, colorconverter, shiftedcolor; glm::vec3 color, colorconverter, shiftedcolor;
for ( unsigned int i = 0; i < m_vertices.size(); ++i ) { for ( unsigned int i = 0; i < m_vertices.size(); ++i ) {
// grab it // grab it
vertex = SafeNormalize( m_vertices[ i ] ); vertex = glm::normalize( m_vertices[ i ] );
// angle between sun and vertex // angle between sun and vertex
const float gamma = std::acos( DotProduct( vertex, m_sundirection ) ); const float gamma = std::acos( glm::dot( vertex, m_sundirection ) );
// warning : major hack!!! .. i had to do something with values under horizon // warning : major hack!!! .. i had to do something with values under horizon
//vertex.y = Clamp<float>( vertex.y, 0.05f, 1.0f ); //vertex.y = Clamp<float>( vertex.y, 0.05f, 1.0f );
@@ -283,7 +282,7 @@ void CSkyDome::RebuildColors() {
float const X = (x / y) * Y; float const X = (x / y) * Y;
float const Z = ((1.0f - x - y) / y) * Y; float const Z = ((1.0f - x - y) / y) * Y;
colorconverter = float3( X, Y, Z ); colorconverter = glm::vec3( X, Y, Z );
color = XYZtoRGB( colorconverter ); color = XYZtoRGB( colorconverter );
colorconverter = RGBtoHSV(color); colorconverter = RGBtoHSV(color);
@@ -292,7 +291,7 @@ void CSkyDome::RebuildColors() {
colorconverter.z *= m_expfactor; colorconverter.z *= m_expfactor;
} else { } else {
// exp scale // exp scale
colorconverter.z = 1.0f - exp( -m_expfactor * colorconverter.z ); colorconverter.z = 1.0f - std::exp( -m_expfactor * colorconverter.z );
} }
// desaturate sky colour, based on overcast level // desaturate sky colour, based on overcast level
@@ -309,12 +308,12 @@ void CSkyDome::RebuildColors() {
// this height-based factor is reduced the farther the sky is up in the sky // this height-based factor is reduced the farther the sky is up in the sky
float const shiftfactor = clamp( interpolate(heightbasedphase, sunbasedphase, sunbasedphase), 0.0f, 1.0f ); float const shiftfactor = clamp( interpolate(heightbasedphase, sunbasedphase, sunbasedphase), 0.0f, 1.0f );
// h = 210 makes for 'typical' sky tone // h = 210 makes for 'typical' sky tone
shiftedcolor = float3( 210.0f, colorconverter.y, colorconverter.z ); shiftedcolor = glm::vec3( 210.0f, colorconverter.y, colorconverter.z );
shiftedcolor = HSVtoRGB( shiftedcolor ); shiftedcolor = HSVtoRGB( shiftedcolor );
color = HSVtoRGB(colorconverter); color = HSVtoRGB(colorconverter);
color = Interpolate( color, shiftedcolor, shiftfactor ); color = interpolate( color, shiftedcolor, shiftfactor );
/* /*
// gamma control // gamma control
color.x = std::pow( color.x, m_gammacorrection ); color.x = std::pow( color.x, m_gammacorrection );
@@ -338,10 +337,10 @@ void CSkyDome::RebuildColors() {
} }
// NOTE: average reduced to 25% makes nice tint value for clouds lit from behind // NOTE: average reduced to 25% makes nice tint value for clouds lit from behind
// down the road we could interpolate between it and full strength average, to improve accuracy of cloud appearance // down the road we could interpolate between it and full strength average, to improve accuracy of cloud appearance
m_averagecolour = averagecolor / m_indices.size(); m_averagecolour = averagecolor / static_cast<float>( m_indices.size() );
m_averagecolour.x = std::max( m_averagecolour.x, 0.0f ); m_averagecolour.r = std::max( m_averagecolour.r, 0.0f );
m_averagecolour.y = std::max( m_averagecolour.y, 0.0f ); m_averagecolour.g = std::max( m_averagecolour.g, 0.0f );
m_averagecolour.z = std::max( m_averagecolour.z, 0.0f ); m_averagecolour.b = std::max( m_averagecolour.b, 0.0f );
if( m_coloursbuffer != -1 ) { if( m_coloursbuffer != -1 ) {
// the colour buffer was already initialized, so on this run we update its content // the colour buffer was already initialized, so on this run we update its content

View File

@@ -1,8 +1,5 @@
#pragma once #pragma once
#include "dumb3d.h"
#include "float3d.h"
// sky gradient based on "A practical analytic model for daylight" // sky gradient based on "A practical analytic model for daylight"
// by A. J. Preetham Peter Shirley Brian Smits (University of Utah) // by A. J. Preetham Peter Shirley Brian Smits (University of Utah)
@@ -13,7 +10,7 @@ public:
void Generate(); void Generate();
void RebuildColors(); void RebuildColors();
bool SetSunPosition( Math3D::vector3 const &Direction ); bool SetSunPosition( glm::vec3 const &Direction );
void SetTurbidity( const float Turbidity = 5.0f ); void SetTurbidity( const float Turbidity = 5.0f );
void SetExposure( const bool Linearexposure, const float Expfactor ); void SetExposure( const bool Linearexposure, const float Expfactor );
@@ -21,30 +18,30 @@ public:
void SetGammaCorrection( const float Gamma = 2.2f ); void SetGammaCorrection( const float Gamma = 2.2f );
// update skydome // update skydome
void Update( Math3D::vector3 const &Sun ); void Update( glm::vec3 const &Sun );
// render skydome to screen // render skydome to screen
void Render(); void Render();
// retrieves average colour of the sky dome // retrieves average colour of the sky dome
float3 GetAverageColor() { return m_averagecolour; } glm::vec3 GetAverageColor() { return m_averagecolour; }
private: private:
// shading parametrs // shading parametrs
float3 m_sundirection; glm::vec3 m_sundirection;
float m_thetasun, m_phisun; float m_thetasun, m_phisun;
float m_turbidity; float m_turbidity;
bool m_linearexpcontrol; bool m_linearexpcontrol;
float m_expfactor; float m_expfactor;
float m_overcast; float m_overcast;
float m_gammacorrection; float m_gammacorrection;
float3 m_averagecolour; glm::vec3 m_averagecolour;
// data // data
int const m_tesselation; int const m_tesselation;
std::vector<float3> m_vertices; std::vector<glm::vec3> m_vertices;
std::vector<std::uint16_t> m_indices; std::vector<std::uint16_t> m_indices;
// std::vector<float3> m_normals; // std::vector<float3> m_normals;
std::vector<float3> m_colours; std::vector<glm::vec3> m_colours;
GLuint m_vertexbuffer{ (GLuint)-1 }; GLuint m_vertexbuffer{ (GLuint)-1 };
GLuint m_indexbuffer{ (GLuint)-1 }; GLuint m_indexbuffer{ (GLuint)-1 };
GLuint m_coloursbuffer{ (GLuint)-1 }; GLuint m_coloursbuffer{ (GLuint)-1 };

14
sun.cpp
View File

@@ -33,9 +33,9 @@ void
cSun::update() { cSun::update() {
move(); move();
Math3D::vector3 position( 0.0f, 0.0f, -2000.0f * Global::fDistanceFactor ); glm::vec3 position( 0.0f, 0.0f, -2000.0f * Global::fDistanceFactor );
position.RotateX( (float)( m_body.elevref * ( M_PI / 180.0 ) ) ); position = glm::rotateX( position, (float)( m_body.elevref * ( M_PI / 180.0 ) ) );
position.RotateY( (float)( -m_body.hrang * ( M_PI / 180.0 ) ) ); position = glm::rotateY( position, (float)( -m_body.hrang * ( M_PI / 180.0 ) ) );
m_position = position; m_position = position;
} }
@@ -63,14 +63,10 @@ cSun::render() {
glPopMatrix(); glPopMatrix();
} }
Math3D::vector3 glm::vec3
cSun::getDirection() { cSun::getDirection() {
Math3D::vector3 position( 0.f, 0.f, -1.f ); return glm::normalize( m_position );
position.RotateX( (float)( m_body.elevref * (M_PI/180.0)) );
position.RotateY( (float)( -m_body.hrang * (M_PI/180.0)) );
position.Normalize();
return position;
} }
float float

7
sun.h
View File

@@ -3,7 +3,6 @@
#include "windows.h" #include "windows.h"
#include "GL/glew.h" #include "GL/glew.h"
#include "GL/wglew.h" #include "GL/wglew.h"
#include "dumb3d.h"
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@@ -20,9 +19,9 @@ public:
void update(); void update();
void render(); void render();
// returns location of the sun in the 3d scene // returns location of the sun in the 3d scene
Math3D::vector3 getPosition() { return m_position; } glm::vec3 getPosition() { return m_position; }
// returns vector pointing at the sun // returns vector pointing at the sun
Math3D::vector3 getDirection(); glm::vec3 getDirection();
// returns current elevation above horizon // returns current elevation above horizon
float getAngle(); float getAngle();
// returns current intensity of the sun // returns current intensity of the sun
@@ -98,5 +97,5 @@ protected:
celestialbody m_body; celestialbody m_body;
observer m_observer; observer m_observer;
Math3D::vector3 m_position; glm::vec3 m_position;
}; };

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#define VERSION_MAJOR 17 #define VERSION_MAJOR 17
#define VERSION_MINOR 626 #define VERSION_MINOR 628
#define VERSION_REVISION 0 #define VERSION_REVISION 0