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;
}
else {
std::string compartmentname;
// set lights with probability depending on the compartment type. TODO: expose this in .mmd file
for( auto &sectionlight : 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 == "\xef\xbb\xbfmodels:" ) ) { // 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
}

View File

@@ -83,10 +83,12 @@ double Global::fFogStart = 1700;
double Global::fFogEnd = 2000;
float Global::Overcast{ 0.1f }; // NOTE: all this weather stuff should be moved elsewhere
int Global::DynamicLightCount = 7;
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];
bool Global::ScaleSpecularValues = false;
//m7todo: po co to?
//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];
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
@@ -223,13 +225,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);
@@ -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
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

View File

@@ -224,11 +224,8 @@ class Global
// TODO: put these things in the renderer
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;

View File

@@ -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 = glm::normalize(Global::daylight.direction);
parser.getTokens(9, false);
do {

View File

@@ -244,8 +244,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<std::string>();
@@ -371,6 +376,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);
@@ -450,7 +459,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("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ć
@@ -462,7 +471,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 + "\"" );
}
}
}
@@ -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 + 2 ].position );
facenormals.emplace_back(
glm::length( facenormal ) > 0.0f ?
glm::length2( facenormal ) > 0.0f ?
glm::normalize( facenormal ) :
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
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
@@ -1517,6 +1534,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;
@@ -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
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);
@@ -1613,12 +1640,16 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *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
@@ -1655,11 +1686,22 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *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)

View File

@@ -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 };

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

74
color.h
View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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

7
moon.h
View File

@@ -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;
};

View File

@@ -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;

View File

@@ -25,6 +25,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 {
@@ -75,14 +81,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 );
// directional light
// TODO, TBD: test omni-directional variant
@@ -207,9 +218,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 ) {
@@ -250,11 +261,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<GLfloat>( 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 );
@@ -621,6 +631,7 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
// change light level based on light level of the occupied track
Global::daylight.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 ) {
@@ -638,18 +649,19 @@ 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) );
}
}
}
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 );
// post-render cleanup
m_renderspecular = false;
if( Dynamic->fShade > 0.0f ) {
// restore regular light level
Global::daylight.intensity = 1.0f;
@@ -760,18 +772,14 @@ opengl_renderer::Render( TSubModel *Submodel, glm::mat4 m) {
// również 0
Bind( Submodel->TextureID );
}
::glColor3fv( glm::value_ptr(Submodel->f4Diffuse) ); // McZapkie-240702: zamiast ub
// ...luminance
if( Global::fLuminance < Submodel->fLight ) {
// zeby swiecilo na kolorowo
World.shader.set_material(glm::vec3(Submodel->f4Diffuse) * Submodel->f4Emision.a);
}
World.shader.set_material(Submodel->f4Specular.x * m_speculartranslucentscalefactor,
Global::fLuminance < Submodel->fLight ? glm::vec3(Submodel->f4Diffuse) * Submodel->f4Emision.a : glm::vec3(0.0f));
// main draw call
m_geometry.draw( Submodel->m_geometry );
if (Global::fLuminance < Submodel->fLight)
World.shader.set_material(glm::vec3(0.0f));
World.shader.set_material(0.0f, 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
Global::daylight.intensity = Dynamic->fShade;
}
m_renderspecular = true;
// render
if( Dynamic->mdLowPolyInt ) {
@@ -1099,18 +1108,19 @@ 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 ) );
}
}
}
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 );
// post-render cleanup
m_renderspecular = false;
if( Dynamic->fShade > 0.0f ) {
// restore regular light level
Global::daylight.intensity = 1.0f;
@@ -1204,21 +1214,16 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel, glm::mat4 m) {
// również 0
Bind( Submodel->TextureID );
}
::glColor3fv( glm::value_ptr(Submodel->f4Diffuse) ); // McZapkie-240702: zamiast ub
// ...luminance
if( Global::fLuminance < Submodel->fLight ) {
// zeby swiecilo na kolorowo
World.shader.set_material(glm::vec3(Submodel->f4Diffuse) * Submodel->f4Emision.a);
}
World.shader.set_material(Submodel->f4Specular.x * m_speculartranslucentscalefactor,
Global::fLuminance < Submodel->fLight ? glm::vec3(Submodel->f4Diffuse) * Submodel->f4Emision.a : glm::vec3(0.0f));
// main draw call
m_geometry.draw(Submodel->m_geometry);
if (Global::fLuminance < Submodel->fLight)
World.shader.set_material(glm::vec3(0.0f));
}
}
World.shader.set_material(0.0f, glm::vec3(0.0f));
}
}
else if( Submodel->eType == TP_FREESPOTLIGHT ) {
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
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
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 color(scenelight.color.x,
scenelight.color.y,

View File

@@ -178,6 +178,10 @@ private:
geometry_handle m_billboardgeometry { 0, 0 };
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
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");
emission_uniform = glGetUniformLocation(id, "emission");
specular_uniform = glGetUniformLocation(id, "specular");
lcount_uniform = glGetUniformLocation(id, "lights_count");
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);
glUniform3f(ambient_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);
}
@@ -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);
}
void gl_program_light::set_material(glm::vec3 &emission)
void gl_program_light::set_material(float specular, glm::vec3 &emission)
{
glUseProgram(id);
glUniform1f(specular_uniform, specular);
glUniform3fv(emission_uniform, 1, glm::value_ptr(emission));
}

View File

@@ -56,13 +56,14 @@ public:
gl_program_light(std::vector<gl_shader>);
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(GLuint id, type t, glm::vec3 &pos, glm::vec3 &dir, float in_cutoff, float out_cutoff,
glm::vec3 &color, float linear, float quadratic);
private:
GLuint ambient_uniform;
GLuint specular_uniform;
GLuint emission_uniform;
GLuint lcount_uniform;
struct light_s

View File

@@ -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 );

3
sky.h
View File

@@ -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) );
};
//---------------------------------------------------------------------------

View File

@@ -101,8 +101,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
@@ -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 ) ) {
// build colors if there's a change in sun position
@@ -173,15 +173,14 @@ void CSkyDome::Render() {
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( 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 );
@@ -267,18 +266,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<float>( vertex.y, 0.05f, 1.0f );
@@ -306,7 +305,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);
@@ -315,7 +314,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
@@ -332,12 +331,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 );
@@ -361,10 +360,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<float>( 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

View File

@@ -14,7 +14,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 );
@@ -22,32 +22,32 @@ 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;
gl_program_mvp m_shader;
// data
int m_tesselation;
std::vector<float3> m_vertices;
std::vector<glm::vec3> m_vertices;
std::vector<std::uint16_t> m_indices;
// std::vector<float3> m_normals;
std::vector<float3> m_colours;
std::vector<glm::vec3> m_colours;
GLuint m_vertexbuffer{ (GLuint)-1 };
GLuint m_indexbuffer{ (GLuint)-1 };
GLuint m_coloursbuffer{ (GLuint)-1 };

14
sun.cpp
View File

@@ -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

7
sun.h
View File

@@ -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;
};

View File

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