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

merge, fixed, sort of works (todo: fix cabin light, stars and fog)

This commit is contained in:
VB
2017-06-29 00:40:11 +02:00
24 changed files with 240 additions and 191 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 == "\xef\xbb\xbfmodels:" ) ) { // 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

@@ -83,10 +83,12 @@ 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
int Global::DynamicLightCount = 7; int Global::DynamicLightCount = 7;
GLfloat Global::whiteLight[] = {1.00f, 1.00f, 1.00f, 1.0f}; bool Global::ScaleSpecularValues = false;
GLfloat Global::noLight[] = {0.00f, 0.00f, 0.00f, 1.0f}; //m7todo: po co to?
GLfloat Global::darkLight[] = {0.03f, 0.03f, 0.03f, 1.0f}; //śladowe //GLfloat Global::whiteLight[] = {1.00f, 1.00f, 1.00f, 1.0f};
GLfloat Global::lightPos[4]; //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
@@ -223,13 +225,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);
@@ -536,6 +531,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

@@ -224,11 +224,8 @@ class Global
// TODO: put these things in the renderer // TODO: put these things in the renderer
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 = glm::normalize(Global::daylight.direction);
parser.getTokens(9, false); parser.getTokens(9, false);
do { do {

View File

@@ -244,8 +244,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>();
@@ -371,6 +376,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);
@@ -450,7 +459,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ć
@@ -462,7 +471,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 + "\"" );
} }
} }
} }
@@ -478,7 +487,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() );
} }
@@ -496,16 +505,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ą)
if( glm::dot( vertexnormal, facenormals[ adjacenvertextidx / 3 ] ) > -0.99f ) {
wsp[ adjacenvertextidx ] = vertexidx; // informacja, że w tym wierzchołku jest już policzony wektor normalny wsp[ adjacenvertextidx ] = vertexidx; // informacja, że w tym wierzchołku jest już policzony wektor normalny
vertexnormal += facenormals[ adjacenvertextidx / 3 ]; 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
@@ -1517,6 +1534,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;
@@ -1600,6 +1626,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);
@@ -1613,12 +1640,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
@@ -1655,11 +1686,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

@@ -2271,34 +2271,32 @@ 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();
Math3D::vector3 moon_dir = -1.0 * m_moon.getDirection(); Global::daylight.direction = -1.0f * m_moon.getDirection();
Global::daylight.direction = glm::vec3(moon_dir.x, moon_dir.y, moon_dir.z);
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();
Math3D::vector3 sun_dir = -1.0 * m_sun.getDirection(); Global::daylight.direction = -1.0f * m_sun.getDirection();
Global::daylight.direction = glm::vec3(sun_dir.x, sun_dir.y, sun_dir.z);
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 );

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

View File

@@ -25,6 +25,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 {
@@ -75,14 +81,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 );
// directional light // directional light
// TODO, TBD: test omni-directional variant // TODO, TBD: test omni-directional variant
@@ -207,9 +218,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 ) {
@@ -250,11 +261,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 );
@@ -621,6 +631,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.intensity = Dynamic->fShade; Global::daylight.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 ) {
@@ -638,18 +649,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 );
} }
} }
} }
if( Dynamic->mdModel )
Render( Dynamic->mdModel, Dynamic->Material(), squaredistance ); 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.intensity = 1.0f; Global::daylight.intensity = 1.0f;
@@ -760,18 +772,14 @@ opengl_renderer::Render( TSubModel *Submodel, glm::mat4 m) {
// również 0 // również 0
Bind( Submodel->TextureID ); Bind( Submodel->TextureID );
} }
::glColor3fv( glm::value_ptr(Submodel->f4Diffuse) ); // McZapkie-240702: zamiast ub
// ...luminance World.shader.set_material(Submodel->f4Specular.x * m_speculartranslucentscalefactor,
if( Global::fLuminance < Submodel->fLight ) { Global::fLuminance < Submodel->fLight ? glm::vec3(Submodel->f4Diffuse) * Submodel->f4Emision.a : glm::vec3(0.0f));
// zeby swiecilo na kolorowo
World.shader.set_material(glm::vec3(Submodel->f4Diffuse) * Submodel->f4Emision.a);
}
// main draw call // main draw call
m_geometry.draw( Submodel->m_geometry ); m_geometry.draw( Submodel->m_geometry );
if (Global::fLuminance < Submodel->fLight) World.shader.set_material(0.0f, glm::vec3(0.0f));
World.shader.set_material(glm::vec3(0.0f));
} }
} }
@@ -1082,6 +1090,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.intensity = Dynamic->fShade; Global::daylight.intensity = Dynamic->fShade;
} }
m_renderspecular = true;
// render // render
if( Dynamic->mdLowPolyInt ) { if( Dynamic->mdLowPolyInt ) {
@@ -1099,18 +1108,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 );
} }
} }
} }
if( Dynamic->mdModel )
Render_Alpha( Dynamic->mdModel, Dynamic->Material(), squaredistance ); 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.intensity = 1.0f; Global::daylight.intensity = 1.0f;
@@ -1204,21 +1214,16 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel, glm::mat4 m) {
// również 0 // również 0
Bind( Submodel->TextureID ); Bind( Submodel->TextureID );
} }
::glColor3fv( glm::value_ptr(Submodel->f4Diffuse) ); // McZapkie-240702: zamiast ub
// ...luminance World.shader.set_material(Submodel->f4Specular.x * m_speculartranslucentscalefactor,
if( Global::fLuminance < Submodel->fLight ) { Global::fLuminance < Submodel->fLight ? glm::vec3(Submodel->f4Diffuse) * Submodel->f4Emision.a : glm::vec3(0.0f));
// zeby swiecilo na kolorowo
World.shader.set_material(glm::vec3(Submodel->f4Diffuse) * Submodel->f4Emision.a);
}
// main draw call // main draw call
m_geometry.draw(Submodel->m_geometry); m_geometry.draw(Submodel->m_geometry);
if (Global::fLuminance < Submodel->fLight) World.shader.set_material(0.0f, glm::vec3(0.0f));
World.shader.set_material(glm::vec3(0.0f));
} }
} }
else if( Submodel->eType == TP_FREESPOTLIGHT ) { else if( Submodel->eType == TP_FREESPOTLIGHT ) {
if( Global::fLuminance < Submodel->fLight ) { if( Global::fLuminance < Submodel->fLight ) {
@@ -1381,11 +1386,12 @@ opengl_renderer::Update_Lights( light_array const &Lights ) {
// but there could still be weaker lights which are closer, so keep looking // but there could still be weaker lights which are closer, so keep looking
continue; continue;
} }
// if the light passed tests so far, it's good enough // if the light passed tests so far, it's good enough
Math3D::vector3 pos = scenelight.position - Global::pCameraPosition;
auto const luminance = Global::fLuminance; // TODO: adjust this based on location, e.g. for tunnels auto const luminance = Global::fLuminance; // TODO: adjust this based on location, e.g. for tunnels
glm::vec3 position(scenelight.position.x, scenelight.position.y, scenelight.position.z); glm::vec3 position(pos.x, pos.y, pos.z);
glm::vec3 direction(scenelight.direction.x, scenelight.direction.y, scenelight.direction.z); glm::vec3 direction(scenelight.direction.x, scenelight.direction.y, scenelight.direction.z);
glm::vec3 color(scenelight.color.x, glm::vec3 color(scenelight.color.x,
scenelight.color.y, scenelight.color.y,

View File

@@ -178,6 +178,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

@@ -114,6 +114,7 @@ gl_program_light::gl_program_light(std::vector<gl_shader> v) : gl_program_mvp(v)
{ {
ambient_uniform = glGetUniformLocation(id, "ambient"); ambient_uniform = glGetUniformLocation(id, "ambient");
emission_uniform = glGetUniformLocation(id, "emission"); emission_uniform = glGetUniformLocation(id, "emission");
specular_uniform = glGetUniformLocation(id, "specular");
lcount_uniform = glGetUniformLocation(id, "lights_count"); lcount_uniform = glGetUniformLocation(id, "lights_count");
for (size_t i = 0; i < MAX_LIGHTS; i++) for (size_t i = 0; i < MAX_LIGHTS; i++)
@@ -131,6 +132,7 @@ gl_program_light::gl_program_light(std::vector<gl_shader> v) : gl_program_mvp(v)
glUseProgram(id); glUseProgram(id);
glUniform3f(ambient_uniform, 0.0f, 0.0f, 0.0f); glUniform3f(ambient_uniform, 0.0f, 0.0f, 0.0f);
glUniform3f(emission_uniform, 0.0f, 0.0f, 0.0f); glUniform3f(emission_uniform, 0.0f, 0.0f, 0.0f);
glUniform1f(specular_uniform, 0.0f);
glUniform1ui(lcount_uniform, 0); glUniform1ui(lcount_uniform, 0);
} }
@@ -166,8 +168,9 @@ void gl_program_light::set_light(GLuint i, type t, glm::vec3 &pos, glm::vec3 &di
glUniform1f(lights_uniform[i].quadratic, quadratic); glUniform1f(lights_uniform[i].quadratic, quadratic);
} }
void gl_program_light::set_material(glm::vec3 &emission) void gl_program_light::set_material(float specular, glm::vec3 &emission)
{ {
glUseProgram(id); glUseProgram(id);
glUniform1f(specular_uniform, specular);
glUniform3fv(emission_uniform, 1, glm::value_ptr(emission)); glUniform3fv(emission_uniform, 1, glm::value_ptr(emission));
} }

View File

@@ -56,13 +56,14 @@ public:
gl_program_light(std::vector<gl_shader>); gl_program_light(std::vector<gl_shader>);
void set_ambient(glm::vec3 &ambient); void set_ambient(glm::vec3 &ambient);
void set_material(glm::vec3 &emission); void set_material(float specular, glm::vec3 &emission);
void set_light_count(GLuint count); void set_light_count(GLuint count);
void set_light(GLuint id, type t, glm::vec3 &pos, glm::vec3 &dir, float in_cutoff, float out_cutoff, void set_light(GLuint id, type t, glm::vec3 &pos, glm::vec3 &dir, float in_cutoff, float out_cutoff,
glm::vec3 &color, float linear, float quadratic); glm::vec3 &color, float linear, float quadratic);
private: private:
GLuint ambient_uniform; GLuint ambient_uniform;
GLuint specular_uniform;
GLuint emission_uniform; GLuint emission_uniform;
GLuint lcount_uniform; GLuint lcount_uniform;
struct light_s struct light_s

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

@@ -101,8 +101,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
@@ -122,7 +122,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
@@ -173,15 +173,14 @@ void CSkyDome::Render() {
glUseProgram(0); glUseProgram(0);
} }
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 );
@@ -267,18 +266,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 );
@@ -306,7 +305,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);
@@ -315,7 +314,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
@@ -332,12 +331,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 );
@@ -361,10 +360,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

@@ -14,7 +14,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 );
@@ -22,32 +22,32 @@ 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;
gl_program_mvp m_shader; gl_program_mvp m_shader;
// data // data
int m_tesselation; int 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