From 8e37307ff5ab1b18a05c94b9cf1d81167ee7357b Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Mon, 26 Jun 2017 22:31:42 +0200 Subject: [PATCH 1/2] minor diagnostics enhancements and null pointer safeguards --- DynObj.cpp | 20 ++++++++++++-------- Model3d.cpp | 2 +- parser.cpp | 9 +++++++-- renderer.cpp | 6 ++++-- 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/DynObj.cpp b/DynObj.cpp index 0e6742f1..7dd448f4 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -539,11 +539,10 @@ TDynamicObject::toggle_lights() { SectionLightsActive = false; } else { - std::string compartmentname; // set lights with probability depending on the compartment type. TODO: expose this in .mmd file for( auto §ionlight : SectionLightLevels ) { - compartmentname = sectionlight.compartment->pName; + std::string const &compartmentname = sectionlight.compartment->pName; if( ( compartmentname.find( "corridor" ) != std::string::npos ) || ( compartmentname.find( "korytarz" ) != std::string::npos ) ) { // corridors are lit 100% of time @@ -584,8 +583,9 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist) pAnimations[i].yUpdate(pAnimations + 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 // te animacje wymagają bananów w modelach! mdModel->GetSMRoot()->SetTranslate(modelShake); @@ -4033,12 +4033,17 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, bool Stop_InternalData = false; pants = NULL; // wskaźnik pierwszego obiektu animującego dla pantografów 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; do { 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 m_materialdata.multi_textures = 0; // czy jest wiele tekstur wymiennych? parser.getTokens(); @@ -5024,13 +5029,12 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, } if (mdModel) - mdModel->Init(); // obrócenie modelu oraz optymalizacja, również zapisanie - // binarnego + mdModel->Init(); // obrócenie modelu oraz optymalizacja, również zapisanie binarnego if (mdLoad) mdLoad->Init(); if (mdLowPolyInt) mdLowPolyInt->Init(); - // sHorn2.CopyIfEmpty(sHorn1); ///żeby jednak trąbił też drugim + Global::asCurrentTexturePath = szTexturePath; // kiedyś uproszczone wnętrze mieszało tekstury nieba } diff --git a/Model3d.cpp b/Model3d.cpp index 1974ba5c..a439772f 100644 --- a/Model3d.cpp +++ b/Model3d.cpp @@ -446,7 +446,7 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic --facecount; // o jeden trójkąt mniej iNumVerts -= 3; // czyli o 3 wierzchołki i -= 3; // wczytanie kolejnego w to miejsce - WriteLog("Degenerated triangle ignored in: \"" + pName + "\", vertice " + std::to_string(i)); + WriteLog("Degenerated triangle ignored in: \"" + pName + "\", vertices " + std::to_string(i) + "-" + std::to_string(i+2)); } if (i > 0) { // jeśli pierwszy trójkąt będzie zdegenerowany, to zostanie usunięty i nie ma co sprawdzać diff --git a/parser.cpp b/parser.cpp index b6b27dfd..68355475 100644 --- a/parser.cpp +++ b/parser.cpp @@ -50,8 +50,13 @@ cParser::cParser( std::string const &Stream, buffertype const Type, std::string // calculate stream size if (mStream) { - mSize = mStream->rdbuf()->pubseekoff(0, std::ios_base::end); - mStream->rdbuf()->pubseekoff(0, std::ios_base::beg); + if( true == mStream->fail() ) { + 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 mSize = 0; diff --git a/renderer.cpp b/renderer.cpp index bc380ecb..ddf75e44 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -656,7 +656,8 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) { } } - Render( Dynamic->mdModel, Dynamic->Material(), squaredistance ); + if( Dynamic->mdModel ) + Render( Dynamic->mdModel, Dynamic->Material(), squaredistance ); if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance ); @@ -1101,7 +1102,8 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) { } } - Render_Alpha( Dynamic->mdModel, Dynamic->Material(), squaredistance ); + if( Dynamic->mdModel ) + Render_Alpha( Dynamic->mdModel, Dynamic->Material(), squaredistance ); if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku Render_Alpha( Dynamic->mdLoad, Dynamic->Material(), squaredistance ); From 49aad8559734b70a6883083718384d95ac2d9c90 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Wed, 28 Jun 2017 21:02:54 +0200 Subject: [PATCH 2/2] build 170628. enabled support for specular component in lighting calculations --- Globals.cpp | 21 +++++-------- Globals.h | 5 +-- Ground.cpp | 2 +- Model3d.cpp | 76 ++++++++++++++++++++++++++++++++++----------- Model3d.h | 1 + World.cpp | 19 ++++++------ color.h | 74 ++++++++++++++++++++++---------------------- lightarray.cpp | 4 +-- lightarray.h | 2 +- moon.cpp | 14 +++------ moon.h | 7 ++--- renderer.cpp | 83 ++++++++++++++++++++++++++++++++++++-------------- renderer.h | 53 +++++++++++++++----------------- sky.cpp | 4 +-- sky.h | 3 +- skydome.cpp | 39 ++++++++++++------------ skydome.h | 17 +++++------ sun.cpp | 14 +++------ sun.h | 7 ++--- version.h | 2 +- 20 files changed, 249 insertions(+), 198 deletions(-) diff --git a/Globals.cpp b/Globals.cpp index 7dddc20f..6401aa1e 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -82,13 +82,10 @@ GLfloat Global::AtmoColor[] = {0.423f, 0.702f, 1.0f}; GLfloat Global::FogColor[] = {0.6f, 0.7f, 0.8f}; double Global::fFogStart = 1700; 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; -int Global::DynamicLightCount{ 3 }; -GLfloat Global::whiteLight[] = {1.00f, 1.00f, 1.00f, 1.0f}; -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]; +int Global::DynamicLightCount { 3 }; +bool Global::ScaleSpecularValues { true }; bool Global::bRollFix = true; // czy wykonać przeliczanie przechyłki bool Global::bJoinEvents = false; // czy grupować eventy o tych samych nazwach 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) { -/* - 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 ); FreeCameraInitAngle.resize( 10 ); 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 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") { // podwójna jasność ambient diff --git a/Globals.h b/Globals.h index 9e0cf512..b4bc804c 100644 --- a/Globals.h +++ b/Globals.h @@ -225,11 +225,8 @@ class Global // TODO: put these things in the renderer static opengl_light DayLight; static int DynamicLightCount; + static bool ScaleSpecularValues; - static GLfloat whiteLight[]; - static GLfloat noLight[]; - static GLfloat darkLight[]; - static GLfloat lightPos[4]; static int iSlowMotion; static TDynamicObject *changeDynObj; static double ABuDebug; diff --git a/Ground.cpp b/Ground.cpp index 4f37e50b..a131644e 100644 --- a/Ground.cpp +++ b/Ground.cpp @@ -1937,7 +1937,7 @@ bool TGround::Init(std::string File) >> Global::DayLight.direction.x >> Global::DayLight.direction.y >> Global::DayLight.direction.z;; - Global::DayLight.direction.Normalize(); + Global::DayLight.direction = glm::normalize( Global::DayLight.direction ); parser.getTokens(9, false); do { diff --git a/Model3d.cpp b/Model3d.cpp index a439772f..7c803815 100644 --- a/Model3d.cpp +++ b/Model3d.cpp @@ -240,8 +240,13 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic if (eType < TP_ROTATOR) readColor(parser, f4Ambient); // ignoruje token przed readColor(parser, f4Diffuse); - if (eType < TP_ROTATOR) - readColor(parser, f4Specular); + if( eType < TP_ROTATOR ) { + 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:" { std::string light = parser.getToken(); @@ -367,6 +372,10 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic readMatrix(parser, *fMatrix); // wczytanie transform if (!fMatrix->IdentityIs()) 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) { // wczytywanie wierzchołków 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 iNumVerts -= 3; // czyli o 3 wierzchołki i -= 3; // wczytanie kolejnego w to miejsce - WriteLog("Degenerated triangle ignored in: \"" + pName + "\", vertices " + std::to_string(i) + "-" + std::to_string(i+2)); + WriteLog("Bad model: degenerated triangle ignored in: \"" + pName + "\", vertices " + std::to_string(i) + "-" + std::to_string(i+2)); } if (i > 0) { // 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 iNumVerts -= 3; // czyli o 3 wierzchołki 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 + 2 ].position ); facenormals.emplace_back( - glm::length( facenormal ) > 0.0f ? + glm::length2( facenormal ) > 0.0f ? glm::normalize( facenormal ) : 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 while (adjacenvertextidx >= 0) { // sumowanie z wektorem normalnym sąsiada (włącznie ze sobą) - wsp[adjacenvertextidx] = vertexidx; // informacja, że w tym wierzchołku jest już policzony wektor normalny - vertexnormal += facenormals[adjacenvertextidx / 3]; + if( glm::dot( vertexnormal, facenormals[ adjacenvertextidx / 3 ] ) > -0.99f ) { + 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 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 + if( glm::length2( vertexnormal ) == 0.0f ) { + WriteLog( "Bad model: zero lenght normal vector generated for sub-model \"" + pName + "\"" ); + } Vertices[ vertexidx ].normal = ( - glm::length( vertexnormal ) > 0.0f ? + glm::length2( vertexnormal ) > 0.0f ? 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 @@ -1516,6 +1533,15 @@ void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic) iNumVerts += submodel.iNumVerts; for( auto &vertex : vertices ) { 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 int type; @@ -1599,6 +1625,7 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector *t, 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 fMatrix = ((iMatrix >= 0) && m) ? m + iMatrix : nullptr; + if (n->size() && (iName >= 0)) { pName = n->at(iName); @@ -1612,12 +1639,16 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector *t, // obiektem "Light_Off" else if (dynamic) { // inaczej wyłączało smugę w latarniach - if ((pName.size() >= 3) && (pName.substr(pName.size() - 3, 3) == "_on")) - { // jeśli jest kontrolką w stanie zapalonym - iVisible = 0; // to domyślnie wyłączyć, żeby się nie nakładało z + if ((pName.size() >= 3) && (pName.substr(pName.size() - 3, 3) == "_on")) { + // jeśli jest kontrolką w stanie zapalonym to domyślnie wyłączyć, + // ż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 @@ -1654,11 +1685,22 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector *t, if( fCosHotspotAngle > 1.0f ) { 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) -/* - 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) diff --git a/Model3d.h b/Model3d.h index 3c74b353..b47d1dce 100644 --- a/Model3d.h +++ b/Model3d.h @@ -96,6 +96,7 @@ private: f4Diffuse { 1.0f,1.0f,1.0f,1.0f }, f4Specular { 0.0f,0.0f,0.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 fSquareMaxDist { 10000.0f * 10000.0f }; float fSquareMinDist { 0.0f }; diff --git a/World.cpp b/World.cpp index f6e53a81..cf94dcee 100644 --- a/World.cpp +++ b/World.cpp @@ -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 float keylightintensity; float twilightfactor; - float3 keylightcolor; + glm::vec3 keylightcolor; if( moonlightlevel > sunlightlevel ) { // rare situations when the moon is brighter than the sun, typically at night Global::SunAngle = m_moon.getAngle(); 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; // if the moon is up, it overrides the twilight 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 { // regular situation with sun as the key light Global::SunAngle = m_sun.getAngle(); 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; // diffuse (sun) intensity goes down after twilight, and reaches minimum 18 degrees below horizon twilightfactor = 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( - float3( 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( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f ), + glm::vec3( 235.0f / 255.0f, 140.0f / 255.0f, 36.0f / 255.0f ), duskfactor ); } // ...update skydome to match the current sun position as well... m_skydome.SetOvercastFactor( Global::Overcast ); - m_skydome.Update( m_sun.getPosition() ); + m_skydome.Update( m_sun.getDirection() ); // ...retrieve current sky colour and brightness... auto const skydomecolour = m_skydome.GetAverageColor(); 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 ); // ...update light colours and intensity. keylightcolor = keylightcolor * diffuselevel; - Global::DayLight.diffuse[ 0 ] = keylightcolor.x; - Global::DayLight.diffuse[ 1 ] = keylightcolor.y; - Global::DayLight.diffuse[ 2 ] = keylightcolor.z; + Global::DayLight.diffuse = glm::vec4( keylightcolor, Global::DayLight.diffuse.a ); + Global::DayLight.specular = glm::vec4( keylightcolor * 0.85f, diffuselevel ); // 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) diff --git a/color.h b/color.h index ed334551..998331a9 100644 --- a/color.h +++ b/color.h @@ -3,28 +3,28 @@ #include "float3d.h" inline -float3 -XYZtoRGB( float3 const &XYZ ) { +glm::vec3 +XYZtoRGB( glm::vec3 const &XYZ ) { // 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 }; // 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 }; - return float3{ + return glm::vec3{ 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 ][ 2 ] + XYZ.y*mi[ 1 ][ 2 ] + XYZ.z*mi[ 2 ][ 2 ] }; } inline -float3 -RGBtoHSV( float3 const &RGB ) { +glm::vec3 +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 min = std::min( std::min( 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.r, RGB.g ), RGB.b ); float const delta = max - min; hsv.z = max; // v @@ -43,13 +43,13 @@ RGBtoHSV( float3 const &RGB ) { hsv.x = NAN; // its now undefined return hsv; } - if( RGB.x >= max ) // > is bogus, just keeps compilor happy - hsv.x = ( RGB.y - RGB.z ) / delta; // between yellow & magenta + if( RGB.r >= max ) // > is bogus, just keeps compilor happy + hsv.x = ( RGB.g - RGB.b ) / delta; // between yellow & magenta else - if( RGB.y >= max ) - hsv.x = 2.0 + ( RGB.y - RGB.x ) / delta; // between cyan & yellow + if( RGB.g >= max ) + hsv.x = 2.0 + ( RGB.g - RGB.r ) / delta; // between cyan & yellow 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 @@ -60,15 +60,15 @@ RGBtoHSV( float3 const &RGB ) { } inline -float3 -HSVtoRGB( float3 const &HSV ) { +glm::vec3 +HSVtoRGB( glm::vec3 const &HSV ) { - float3 rgb; + glm::vec3 rgb; if( HSV.y <= 0.0 ) { // < is bogus, just shuts up warnings - rgb.x = HSV.z; - rgb.y = HSV.z; - rgb.z = HSV.z; + rgb.r = HSV.z; + rgb.g = HSV.z; + rgb.b = HSV.z; return rgb; } float hh = HSV.x; @@ -82,36 +82,36 @@ HSVtoRGB( float3 const &HSV ) { switch( i ) { case 0: - rgb.x = HSV.z; - rgb.y = t; - rgb.z = p; + rgb.r = HSV.z; + rgb.g = t; + rgb.b = p; break; case 1: - rgb.x = q; - rgb.y = HSV.z; - rgb.z = p; + rgb.r = q; + rgb.g = HSV.z; + rgb.b = p; break; case 2: - rgb.x = p; - rgb.y = HSV.z; - rgb.z = t; + rgb.r = p; + rgb.g = HSV.z; + rgb.b = t; break; case 3: - rgb.x = p; - rgb.y = q; - rgb.z = HSV.z; + rgb.r = p; + rgb.g = q; + rgb.b = HSV.z; break; case 4: - rgb.x = t; - rgb.y = p; - rgb.z = HSV.z; + rgb.r = t; + rgb.g = p; + rgb.b = HSV.z; break; case 5: default: - rgb.x = HSV.z; - rgb.y = p; - rgb.z = q; + rgb.r = HSV.z; + rgb.g = p; + rgb.b = q; break; } return rgb; diff --git a/lightarray.cpp b/lightarray.cpp index 8a9bc1a3..8a0412a3 100644 --- a/lightarray.cpp +++ b/lightarray.cpp @@ -47,12 +47,12 @@ light_array::update() { if( light.index == 0 ) { // front light set 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 { // rear light set 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.z = -light.direction.z; } diff --git a/lightarray.h b/lightarray.h index 34b317d9..91e45ef0 100644 --- a/lightarray.h +++ b/lightarray.h @@ -20,7 +20,7 @@ public: 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 + 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 float intensity{ 0.0f }; // (combined) intensity of the light(s) int count{ 0 }; // number (or pattern) of active light(s) diff --git a/moon.cpp b/moon.cpp index a7db52e5..a6566d5e 100644 --- a/moon.cpp +++ b/moon.cpp @@ -36,9 +36,9 @@ void cMoon::update() { move(); - Math3D::vector3 position( 0.0f, 0.0f, -2000.0f * Global::fDistanceFactor ); - position.RotateX( (float)( m_body.elevref * ( M_PI / 180.0 ) ) ); - position.RotateY( (float)( -m_body.hrang * ( M_PI / 180.0 ) ) ); + glm::vec3 position( 0.0f, 0.0f, -2000.0f * Global::fDistanceFactor ); + position = glm::rotateX( position, (float)( m_body.elevref * ( M_PI / 180.0 ) ) ); + position = glm::rotateY( position, (float)( -m_body.hrang * ( M_PI / 180.0 ) ) ); m_position = position; } @@ -59,14 +59,10 @@ cMoon::render() { glPopMatrix(); } -Math3D::vector3 +glm::vec3 cMoon::getDirection() { - Math3D::vector3 position( 0.f, 0.f, -1.f ); - position.RotateX( (float)( m_body.elevref * (M_PI/180.0)) ); - position.RotateY( (float)( -m_body.hrang * (M_PI/180.0)) ); - position.Normalize(); - return position; + return glm::normalize( m_position ); } float diff --git a/moon.h b/moon.h index baa7030c..c0caaa79 100644 --- a/moon.h +++ b/moon.h @@ -3,7 +3,6 @@ #include "windows.h" #include "GL/glew.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 @@ -18,9 +17,9 @@ public: void update(); void render(); // 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 - Math3D::vector3 getDirection(); + glm::vec3 getDirection(); // returns current elevation above horizon float getAngle() const; // returns current intensity of the sun @@ -101,6 +100,6 @@ protected: celestialbody m_body; observer m_observer; - Math3D::vector3 m_position; + glm::vec3 m_position; float m_phase; }; diff --git a/renderer.cpp b/renderer.cpp index ddf75e44..04b4c99e 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -24,6 +24,12 @@ http://mozilla.org/MPL/2.0/. opengl_renderer GfxRenderer; 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 bool opengl_camera::visible( bounding_area const &Area ) const { @@ -74,14 +80,19 @@ opengl_renderer::Init( GLFWwindow *Window ) { glPointSize( 3.0f ); glEnable( GL_POINT_SMOOTH ); - glEnable( GL_COLOR_MATERIAL ); - glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE ); + ::glLightModeli( GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR ); + ::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 - GLfloat ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient ); - glEnable( GL_LIGHTING ); - glEnable( GL_LIGHT0 ); + ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr(m_baseambient) ); + ::glEnable( GL_LIGHTING ); + ::glEnable( GL_LIGHT0 ); Global::DayLight.id = opengl_renderer::sunlight; // directional light @@ -205,9 +216,9 @@ opengl_renderer::Render( world_environment *Environment ) { Environment->m_stars.render(); float const duskfactor = 1.0f - clamp( std::abs( Environment->m_sun.getAngle() ), 0.0f, 12.0f ) / 12.0f; - float3 suncolor = interpolate( - float3( 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 suncolor = interpolate( + glm::vec3( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f ), + glm::vec3( 235.0f / 255.0f, 140.0f / 255.0f, 36.0f / 255.0f ), duskfactor ); if( DebugModeFlag == true ) { @@ -248,11 +259,10 @@ opengl_renderer::Render( world_environment *Environment ) { // moon { 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( 1.0 - Global::fLuminance * 0.5 ) ); - auto const moonvector = Environment->m_moon.getDirection(); - auto const moonposition = modelview * glm::vec4( moonvector.x, moonvector.y, moonvector.z, 1.0f ); + auto const moonposition = modelview * glm::vec4( Environment->m_moon.getDirection(), 1.0f ); ::glPushMatrix(); ::glLoadIdentity(); // macierz jedynkowa ::glTranslatef( moonposition.x, moonposition.y, moonposition.z ); @@ -553,7 +563,7 @@ opengl_renderer::Render( TGroundNode *Node ) { ::glColor4fv( glm::value_ptr( 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 auto const linewidth = clamp( 0.5 * linealpha + Node->fLineThickness * Node->m_radius / 1000.0, 1.0, 32.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 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 if( Dynamic->mdLowPolyInt ) { @@ -650,8 +661,7 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) { if( Dynamic->InteriorLightLevel > 0.0f ) { // reset the overall ambient - GLfloat ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient ); + ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr(m_baseambient) ); } } } @@ -663,6 +673,7 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) { Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance ); // post-render cleanup + m_renderspecular = false; if( Dynamic->fShade > 0.0f ) { // restore regular light level Global::DayLight.apply_intensity(); @@ -747,6 +758,9 @@ opengl_renderer::Render( TSubModel *Submodel ) { // renderowanie obiektów OpenGL if( Submodel->iAlpha & Submodel->iFlags & 0x1F ) // rysuj gdy element nieprzezroczysty { + if( true == Submodel->m_normalizenormals ) { + ::glEnable( GL_NORMALIZE ); + } // material configuration: // textures... if( Submodel->TextureID < 0 ) @@ -757,7 +771,12 @@ opengl_renderer::Render( TSubModel *Submodel ) { // również 0 Bind( Submodel->TextureID ); } + // ...colors... ::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 if( Global::fLuminance < Submodel->fLight ) { // zeby swiecilo na kolorowo @@ -768,10 +787,15 @@ opengl_renderer::Render( TSubModel *Submodel ) { m_geometry.draw( Submodel->m_geometry ); // 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 ) { // 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( noemission ) ); + ::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( colors::none ) ); + } + if( true == Submodel->m_normalizenormals ) { + ::glDisable( GL_NORMALIZE ); } } } @@ -1007,7 +1031,7 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) { ::glColor4fv( glm::value_ptr( 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 ) ) ) ); auto const linewidth = clamp( 0.5 * linealpha + Node->fLineThickness * Node->m_radius / 1000.0, 1.0, 32.0 ); if( linewidth > 1.0 ) { @@ -1079,6 +1103,7 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) { // change light level based on light level of the occupied track Global::DayLight.apply_intensity( Dynamic->fShade ); } + m_renderspecular = true; // render if( Dynamic->mdLowPolyInt ) { @@ -1096,8 +1121,7 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) { if( Dynamic->InteriorLightLevel > 0.0f ) { // reset the overall ambient - GLfloat ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient ); + ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( m_baseambient ) ); } } } @@ -1109,6 +1133,7 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) { Render_Alpha( Dynamic->mdLoad, Dynamic->Material(), squaredistance ); // post-render cleanup + m_renderspecular = false; if( Dynamic->fShade > 0.0f ) { // restore regular light level Global::DayLight.apply_intensity(); @@ -1192,6 +1217,9 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) { // renderowanie obiektów OpenGL if( Submodel->iAlpha & Submodel->iFlags & 0x2F ) // rysuj gdy element przezroczysty { + if( true == Submodel->m_normalizenormals ) { + ::glEnable( GL_NORMALIZE ); + } // textures... if( Submodel->TextureID < 0 ) { // zmienialne skóry Bind( Submodel->ReplacableSkinId[ -Submodel->TextureID ] ); @@ -1200,7 +1228,11 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) { // również 0 Bind( Submodel->TextureID ); } + // ...colors... ::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 if( Global::fLuminance < Submodel->fLight ) { // zeby swiecilo na kolorowo @@ -1211,10 +1243,15 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) { m_geometry.draw( Submodel->m_geometry ); // 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 ) { // 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( noemission ) ); + ::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( colors::none ) ); + } + if( true == Submodel->m_normalizenormals ) { + ::glDisable( GL_NORMALIZE ); } } } @@ -1401,7 +1438,7 @@ opengl_renderer::Update_Lights( light_array const &Lights ) { continue; } // 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; auto luminance = Global::fLuminance; // TODO: adjust this based on location, e.g. for tunnels diff --git a/renderer.h b/renderer.h index 43332c5b..b17c3b23 100644 --- a/renderer.h +++ b/renderer.h @@ -21,53 +21,44 @@ http://mozilla.org/MPL/2.0/. struct opengl_light { GLuint id{ (GLuint)-1 }; - Math3D::vector3 direction; - GLfloat position[ 4 ]; // 4th parameter specifies directional(0) or omni-directional(1) light source - GLfloat ambient[ 4 ]; - GLfloat diffuse[ 4 ]; - GLfloat specular[ 4 ]; - - 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 - } + glm::vec3 direction; + glm::vec4 + position { 0.0f, 0.0f, 0.0f, 1.0f }, // 4th parameter specifies directional(0) or omni-directional(1) light source + ambient { 0.0f, 0.0f, 0.0f, 1.0f }, + diffuse { 1.0f, 1.0f, 1.0f, 1.0f }, + specular { 1.0f, 1.0f, 1.0f, 1.0f }; inline void apply_intensity( float const Factor = 1.0f ) { if( Factor == 1.0 ) { - glLightfv( id, GL_AMBIENT, ambient ); - glLightfv( id, GL_DIFFUSE, diffuse ); - glLightfv( id, GL_SPECULAR, specular ); + glLightfv( id, GL_AMBIENT, glm::value_ptr(ambient) ); + glLightfv( id, GL_DIFFUSE, glm::value_ptr(diffuse) ); + glLightfv( id, GL_SPECULAR, glm::value_ptr(specular) ); } else { // 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 ] ); - float4 scaleddiffuse( diffuse[ 0 ] * Factor, diffuse[ 1 ] * Factor, diffuse[ 2 ] * Factor, diffuse[ 3 ] ); - float4 scaledspecular( specular[ 0 ] * Factor, specular[ 1 ] * Factor, specular[ 2 ] * Factor, specular[ 3 ] ); - glLightfv( id, GL_AMBIENT, &scaledambient.x ); - glLightfv( id, GL_DIFFUSE, &scaleddiffuse.x ); - glLightfv( id, GL_SPECULAR, &scaledspecular.x ); + glm::vec4 scaledambient( ambient.r * Factor, ambient.g * Factor, ambient.b * Factor, ambient.a ); + glm::vec4 scaleddiffuse( diffuse.r * Factor, diffuse.g * Factor, diffuse.b * Factor, diffuse.a ); + glm::vec4 scaledspecular( specular.r * Factor, specular.g * Factor, specular.b * Factor, specular.a ); + glLightfv( id, GL_AMBIENT, glm::value_ptr(scaledambient) ); + glLightfv( id, GL_DIFFUSE, glm::value_ptr(scaleddiffuse) ); + glLightfv( id, GL_SPECULAR, glm::value_ptr(scaledspecular) ); } } inline void apply_angle() { - glLightfv( id, GL_POSITION, position ); - if( position[ 3 ] == 1.0f ) { - GLfloat directionarray[] = { (GLfloat)direction.x, (GLfloat)direction.y, (GLfloat)direction.z }; - glLightfv( id, GL_SPOT_DIRECTION, directionarray ); + glLightfv( id, GL_POSITION, glm::value_ptr(position) ); + if( position.w == 1.0f ) { + glLightfv( id, GL_SPOT_DIRECTION, glm::value_ptr(direction) ); } } inline - void set_position( Math3D::vector3 const &Position ) { + void set_position( glm::vec3 const &Position ) { - position[ 0 ] = Position.x; - position[ 1 ] = Position.y; - position[ 2 ] = Position.z; + position = glm::vec4( Position, position.w ); } }; @@ -229,6 +220,10 @@ private: geometry_handle m_billboardgeometry { 0, 0 }; GLUquadricObj *m_quadric; // helper object for drawing debug mode scene elements std::vector 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 }; }; diff --git a/sky.cpp b/sky.cpp index 61aa81d1..284825ab 100644 --- a/sky.cpp +++ b/sky.cpp @@ -27,14 +27,14 @@ void TSky::Init() mdCloud = TModelsManager::GetModel( Global::asSky ); }; -void TSky::Render( float3 const &Tint ) +void TSky::Render( glm::vec3 const &Tint ) { if (mdCloud) { // jeśli jest model nieba // setup ::glEnable( GL_LIGHTING ); GfxRenderer.Disable_Lights(); - ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, &Tint.x ); + ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr(Tint) ); // render GfxRenderer.Render( mdCloud, nullptr, 100.0 ); GfxRenderer.Render_Alpha( mdCloud, nullptr, 100.0 ); diff --git a/sky.h b/sky.h index 1117957a..ebee49a2 100644 --- a/sky.h +++ b/sky.h @@ -11,7 +11,6 @@ http://mozilla.org/MPL/2.0/. #pragma once #include "Model3d.h" -#include "Float3d.h" class TSky { @@ -22,7 +21,7 @@ class TSky TSky(); ~TSky(); 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) ); }; //--------------------------------------------------------------------------- diff --git a/skydome.cpp b/skydome.cpp index 27074616..7d136971 100644 --- a/skydome.cpp +++ b/skydome.cpp @@ -86,8 +86,8 @@ void CSkyDome::Generate() { // m_normals.emplace_back( float3( x * zr, -y * zr, -z ) ); */ // cartesian to opengl swap: -x, -z, -y - m_vertices.emplace_back( float3( -x * zr, -z - offset, -y * zr ) * radius ); - m_colours.emplace_back( float3( 0.75f, 0.75f, 0.75f ) ); // placeholder + m_vertices.emplace_back( glm::vec3( -x * zr, -z - offset, -y * zr ) * radius ); + m_colours.emplace_back( glm::vec3( 0.75f, 0.75f, 0.75f ) ); // placeholder if( (i == 0) || (j == 0) ) { // 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 ) ) { // build colors if there's a change in sun position @@ -150,15 +150,14 @@ void CSkyDome::Render() { ::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( sundirection == m_sundirection ) { + if( Direction == m_sundirection ) { return false; } - m_sundirection = sundirection; + m_sundirection = Direction; m_thetasun = std::acosf( m_sundirection.y ); m_phisun = std::atan2( m_sundirection.z, m_sundirection.x ); @@ -244,18 +243,18 @@ void CSkyDome::RebuildColors() { zenithluminance = PerezFunctionO1( perezluminance, m_thetasun, zenithluminance ); // 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 - float3 vertex; - float3 color, colorconverter, shiftedcolor; + glm::vec3 vertex; + glm::vec3 color, colorconverter, shiftedcolor; for ( unsigned int i = 0; i < m_vertices.size(); ++i ) { // grab it - vertex = SafeNormalize( m_vertices[ i ] ); + vertex = glm::normalize( m_vertices[ i ] ); // 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 //vertex.y = Clamp( vertex.y, 0.05f, 1.0f ); @@ -283,7 +282,7 @@ void CSkyDome::RebuildColors() { float const X = (x / 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 ); colorconverter = RGBtoHSV(color); @@ -292,7 +291,7 @@ void CSkyDome::RebuildColors() { colorconverter.z *= m_expfactor; } else { // 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 @@ -309,12 +308,12 @@ void CSkyDome::RebuildColors() { // 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 ); // 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 ); color = HSVtoRGB(colorconverter); - color = Interpolate( color, shiftedcolor, shiftfactor ); + color = interpolate( color, shiftedcolor, shiftfactor ); /* // gamma control 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 // 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.x = std::max( m_averagecolour.x, 0.0f ); - m_averagecolour.y = std::max( m_averagecolour.y, 0.0f ); - m_averagecolour.z = std::max( m_averagecolour.z, 0.0f ); + m_averagecolour = averagecolor / static_cast( m_indices.size() ); + m_averagecolour.r = std::max( m_averagecolour.r, 0.0f ); + m_averagecolour.g = std::max( m_averagecolour.g, 0.0f ); + m_averagecolour.b = std::max( m_averagecolour.b, 0.0f ); if( m_coloursbuffer != -1 ) { // the colour buffer was already initialized, so on this run we update its content diff --git a/skydome.h b/skydome.h index ba625975..e515bc3e 100644 --- a/skydome.h +++ b/skydome.h @@ -1,8 +1,5 @@ #pragma once -#include "dumb3d.h" -#include "float3d.h" - // sky gradient based on "A practical analytic model for daylight" // by A. J. Preetham Peter Shirley Brian Smits (University of Utah) @@ -13,7 +10,7 @@ public: void Generate(); void RebuildColors(); - bool SetSunPosition( Math3D::vector3 const &Direction ); + bool SetSunPosition( glm::vec3 const &Direction ); void SetTurbidity( const float Turbidity = 5.0f ); void SetExposure( const bool Linearexposure, const float Expfactor ); @@ -21,30 +18,30 @@ public: void SetGammaCorrection( const float Gamma = 2.2f ); // update skydome - void Update( Math3D::vector3 const &Sun ); + void Update( glm::vec3 const &Sun ); // render skydome to screen void Render(); // retrieves average colour of the sky dome - float3 GetAverageColor() { return m_averagecolour; } + glm::vec3 GetAverageColor() { return m_averagecolour; } private: // shading parametrs - float3 m_sundirection; + glm::vec3 m_sundirection; float m_thetasun, m_phisun; float m_turbidity; bool m_linearexpcontrol; float m_expfactor; float m_overcast; float m_gammacorrection; - float3 m_averagecolour; + glm::vec3 m_averagecolour; // data int const m_tesselation; - std::vector m_vertices; + std::vector m_vertices; std::vector m_indices; // std::vector m_normals; - std::vector m_colours; + std::vector m_colours; GLuint m_vertexbuffer{ (GLuint)-1 }; GLuint m_indexbuffer{ (GLuint)-1 }; GLuint m_coloursbuffer{ (GLuint)-1 }; diff --git a/sun.cpp b/sun.cpp index d27e3619..55db2f00 100644 --- a/sun.cpp +++ b/sun.cpp @@ -33,9 +33,9 @@ void cSun::update() { move(); - Math3D::vector3 position( 0.0f, 0.0f, -2000.0f * Global::fDistanceFactor ); - position.RotateX( (float)( m_body.elevref * ( M_PI / 180.0 ) ) ); - position.RotateY( (float)( -m_body.hrang * ( M_PI / 180.0 ) ) ); + glm::vec3 position( 0.0f, 0.0f, -2000.0f * Global::fDistanceFactor ); + position = glm::rotateX( position, (float)( m_body.elevref * ( M_PI / 180.0 ) ) ); + position = glm::rotateY( position, (float)( -m_body.hrang * ( M_PI / 180.0 ) ) ); m_position = position; } @@ -63,14 +63,10 @@ cSun::render() { glPopMatrix(); } -Math3D::vector3 +glm::vec3 cSun::getDirection() { - Math3D::vector3 position( 0.f, 0.f, -1.f ); - position.RotateX( (float)( m_body.elevref * (M_PI/180.0)) ); - position.RotateY( (float)( -m_body.hrang * (M_PI/180.0)) ); - position.Normalize(); - return position; + return glm::normalize( m_position ); } float diff --git a/sun.h b/sun.h index aa659a21..4ab54d10 100644 --- a/sun.h +++ b/sun.h @@ -3,7 +3,6 @@ #include "windows.h" #include "GL/glew.h" #include "GL/wglew.h" -#include "dumb3d.h" ////////////////////////////////////////////////////////////////////////////////////////// @@ -20,9 +19,9 @@ public: void update(); void render(); // 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 - Math3D::vector3 getDirection(); + glm::vec3 getDirection(); // returns current elevation above horizon float getAngle(); // returns current intensity of the sun @@ -98,5 +97,5 @@ protected: celestialbody m_body; observer m_observer; - Math3D::vector3 m_position; + glm::vec3 m_position; }; diff --git a/version.h b/version.h index 9031f529..063844fb 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 17 -#define VERSION_MINOR 626 +#define VERSION_MINOR 628 #define VERSION_REVISION 0