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

virtual opengl matrix stack, light glare billboards

This commit is contained in:
tmj-fstate
2017-03-23 00:09:28 +01:00
parent f4a5f60465
commit 2c76a4418e
15 changed files with 498 additions and 40 deletions

View File

@@ -111,12 +111,12 @@ vector3 TCamera::GetDirection()
return (Normalize(Vec)); return (Normalize(Vec));
} }
/*
bool TCamera::SetMatrix() bool TCamera::SetMatrix()
{ {
glRotated( -Roll * 180.0f / M_PI, 0, 0, 1 ); // po wyłączeniu tego kręci się pojazd, a sceneria nie glRotated( -Roll * 180.0 / M_PI, 0.0, 0.0, 1.0 ); // po wyłączeniu tego kręci się pojazd, a sceneria nie
glRotated( -Pitch * 180.0f / M_PI, 1, 0, 0 ); glRotated( -Pitch * 180.0 / M_PI, 1.0, 0.0, 0.0 );
glRotated( -Yaw * 180.0f / M_PI, 0, 1, 0 ); // w zewnętrznym widoku: kierunek patrzenia glRotated( -Yaw * 180.0 / M_PI, 0.0, 1.0, 0.0 ); // w zewnętrznym widoku: kierunek patrzenia
if( Type == tp_Follow ) if( Type == tp_Follow )
{ {
@@ -132,7 +132,7 @@ bool TCamera::SetMatrix()
Global::SetCameraPosition(Pos); // było +pOffset Global::SetCameraPosition(Pos); // było +pOffset
return true; return true;
} }
*/
bool TCamera::SetMatrix( glm::mat4 &Matrix ) { bool TCamera::SetMatrix( glm::mat4 &Matrix ) {
Matrix = glm::rotate( Matrix, (float)-Roll, glm::vec3( 0.0f, 0.0f, 1.0f ) ); // po wyłączeniu tego kręci się pojazd, a sceneria nie Matrix = glm::rotate( Matrix, (float)-Roll, glm::vec3( 0.0f, 0.0f, 1.0f ) ); // po wyłączeniu tego kręci się pojazd, a sceneria nie
@@ -157,9 +157,9 @@ bool TCamera::SetMatrix( glm::mat4 &Matrix ) {
void TCamera::SetCabMatrix(vector3 &p) void TCamera::SetCabMatrix(vector3 &p)
{ // ustawienie widoku z kamery bez przesunięcia robionego przez OpenGL - nie powinno tak trząść { // ustawienie widoku z kamery bez przesunięcia robionego przez OpenGL - nie powinno tak trząść
glRotated(-Roll * 180.0f / M_PI, 0, 0, 1); glRotated(-Roll * 180.0 / M_PI, 0.0, 0.0, 1.0);
glRotated(-Pitch * 180.0f / M_PI, 1, 0, 0); glRotated(-Pitch * 180.0 / M_PI, 1.0, 0.0, 0.0);
glRotated(-Yaw * 180.0f / M_PI, 0, 1, 0); // w zewnętrznym widoku: kierunek patrzenia glRotated(-Yaw * 180.0 / M_PI, 0.0, 1.0, 0.0); // w zewnętrznym widoku: kierunek patrzenia
if (Type == tp_Follow) if (Type == tp_Follow)
gluLookAt(Pos.x - p.x, Pos.y - p.y, Pos.z - p.z, LookAt.x - p.x, LookAt.y - p.y, gluLookAt(Pos.x - p.x, Pos.y - p.y, Pos.z - p.z, LookAt.x - p.x, LookAt.y - p.y,
LookAt.z - p.z, vUp.x, vUp.y, vUp.z); // Ra: pOffset is zero LookAt.z - p.z, vUp.x, vUp.y, vUp.z); // Ra: pOffset is zero

View File

@@ -48,9 +48,7 @@ class TCamera
void Update(); void Update();
vector3 GetDirection(); vector3 GetDirection();
// vector3 inline GetCrossPos() { return Pos+GetDirection()*CrossDist+CrossPos; }; // vector3 inline GetCrossPos() { return Pos+GetDirection()*CrossDist+CrossPos; };
/*
bool SetMatrix(); bool SetMatrix();
*/
bool SetMatrix(glm::mat4 &Matrix); bool SetMatrix(glm::mat4 &Matrix);
void SetCabMatrix( vector3 &p ); void SetCabMatrix( vector3 &p );
void RaLook(); void RaLook();

View File

@@ -571,7 +571,11 @@ void TGroundNode::RenderDL()
{ // obiekty renderowane niezależnie od odległości { // obiekty renderowane niezależnie od odległości
case TP_SUBMODEL: case TP_SUBMODEL:
TSubModel::fSquareDist = 0; TSubModel::fSquareDist = 0;
#ifdef EU07_USE_OLD_RENDERCODE
return smTerrain->RenderDL(); return smTerrain->RenderDL();
#else
GfxRenderer.Render( smTerrain );
#endif
} }
// if (pTriGroup) if (pTriGroup!=this) return; //wyświetla go inny obiekt // if (pTriGroup) if (pTriGroup!=this) return; //wyświetla go inny obiekt
double mgn = SquareMagnitude(pCenter - Global::pCameraPosition) / Global::ZoomFactor; double mgn = SquareMagnitude(pCenter - Global::pCameraPosition) / Global::ZoomFactor;

View File

@@ -320,8 +320,10 @@ int TSubModel::Load(cParser &parser, TModel3d *Model, int Pos, bool dynamic)
fCosFalloffAngle = cos(DegToRad(0.5 * fCosFalloffAngle)); fCosFalloffAngle = cos(DegToRad(0.5 * fCosFalloffAngle));
fCosHotspotAngle = cos(DegToRad(0.5 * fCosHotspotAngle)); fCosHotspotAngle = cos(DegToRad(0.5 * fCosHotspotAngle));
iNumVerts = 1; iNumVerts = 1;
iFlags |= 0x4010; // rysowane w cyklu nieprzezroczystych, macierz musi /*
// zostać bez zmiany iFlags |= 0x4010; // rysowane w cyklu nieprzezroczystych, macierz musi zostać bez zmiany
*/
iFlags |= 0x4030; // drawn both in solid (light point) and transparent (light glare) phases
} }
else if (eType < TP_ROTATOR) else if (eType < TP_ROTATOR)
{ {
@@ -967,9 +969,9 @@ void TSubModel::RaAnimation(TAnimType a)
if (iAnimOwner != iInstance) if (iAnimOwner != iInstance)
break; // cudza animacja break; // cudza animacja
glTranslatef(v_TransVector.x, v_TransVector.y, v_TransVector.z); glTranslatef(v_TransVector.x, v_TransVector.y, v_TransVector.z);
glRotatef(v_Angles.x, 1.0, 0.0, 0.0); glRotatef(v_Angles.x, 1.0f, 0.0f, 0.0f);
glRotatef(v_Angles.y, 0.0, 1.0, 0.0); glRotatef(v_Angles.y, 0.0f, 1.0f, 0.0f);
glRotatef(v_Angles.z, 0.0, 0.0, 1.0); glRotatef(v_Angles.z, 0.0f, 0.0f, 1.0f);
break; break;
case at_SecondsJump: // sekundy z przeskokiem case at_SecondsJump: // sekundy z przeskokiem
glRotatef(floor(GlobalTime->mr) * 6.0, 0.0, 1.0, 0.0); glRotatef(floor(GlobalTime->mr) * 6.0, 0.0, 1.0, 0.0);
@@ -999,11 +1001,13 @@ void TSubModel::RaAnimation(TAnimType a)
break; break;
case at_Billboard: // obrót w pionie do kamery case at_Billboard: // obrót w pionie do kamery
{ {
/*
matrix4x4 mat; // potrzebujemy współrzędne przesunięcia środka układu matrix4x4 mat; // potrzebujemy współrzędne przesunięcia środka układu
// współrzędnych submodelu // współrzędnych submodelu
glGetDoublev(GL_MODELVIEW_MATRIX, mat.getArray()); // pobranie aktualnej matrycy glGetDoublev(GL_MODELVIEW_MATRIX, mat.getArray()); // pobranie aktualnej matrycy
float3 gdzie = float3(mat[3][0], mat[3][1], */
mat[3][2]); // początek układu współrzędnych submodelu względem kamery matrix4x4 mat; mat.OpenGL_Matrix( OpenGLMatrices.data_array( GL_MODELVIEW ) );
float3 gdzie = float3(mat[3][0], mat[3][1], mat[3][2]); // początek układu współrzędnych submodelu względem kamery
glLoadIdentity(); // macierz jedynkowa glLoadIdentity(); // macierz jedynkowa
glTranslatef(gdzie.x, gdzie.y, gdzie.z); // początek układu zostaje bez glTranslatef(gdzie.x, gdzie.y, gdzie.z); // początek układu zostaje bez
// zmian // zmian
@@ -1020,9 +1024,8 @@ void TSubModel::RaAnimation(TAnimType a)
glRotated(-fmod(Global::fTimeAngleDeg, 360.0), 0.0, 1.0, 0.0); // obrót dobowy osi OX glRotated(-fmod(Global::fTimeAngleDeg, 360.0), 0.0, 1.0, 0.0); // obrót dobowy osi OX
break; break;
case at_IK11: // ostatni element animacji szkieletowej (podudzie, stopa) case at_IK11: // ostatni element animacji szkieletowej (podudzie, stopa)
glRotatef(v_Angles.z, 0.0, 1.0, 0.0); // obrót względem osi pionowej glRotatef(v_Angles.z, 0.0f, 1.0f, 0.0f); // obrót względem osi pionowej (azymut)
// (azymut) glRotatef(v_Angles.x, 1.0f, 0.0f, 0.0f); // obrót względem poziomu (deklinacja)
glRotatef(v_Angles.x, 1.0, 0.0, 0.0); // obrót względem poziomu (deklinacja)
break; break;
case at_DigiClk: // animacja zegara cyfrowego case at_DigiClk: // animacja zegara cyfrowego
{ // ustawienie animacji w submodelach potomnych { // ustawienie animacji w submodelach potomnych
@@ -1048,6 +1051,7 @@ void TSubModel::RaAnimation(TAnimType a)
} }
}; };
#ifdef EU07_USE_OLD_RENDERCODE
void TSubModel::RenderDL() void TSubModel::RenderDL()
{ // główna procedura renderowania przez DL { // główna procedura renderowania przez DL
if( ( iVisible ) if( ( iVisible )
@@ -1228,6 +1232,7 @@ void TSubModel::RenderAlphaDL()
if (iAlpha & iFlags & 0x2F000000) if (iAlpha & iFlags & 0x2F000000)
Next->RenderAlphaDL(); Next->RenderAlphaDL();
}; // RenderAlpha }; // RenderAlpha
#endif
void TSubModel::RenderVBO() void TSubModel::RenderVBO()
{ // główna procedura renderowania przez VBO { // główna procedura renderowania przez VBO
@@ -1271,8 +1276,11 @@ void TSubModel::RenderVBO()
} }
else if (eType == TP_FREESPOTLIGHT) else if (eType == TP_FREESPOTLIGHT)
{ // wersja VBO { // wersja VBO
/*
matrix4x4 mat; // macierz opisuje układ renderowania względem kamery matrix4x4 mat; // macierz opisuje układ renderowania względem kamery
glGetDoublev(GL_MODELVIEW_MATRIX, mat.getArray()); glGetDoublev(GL_MODELVIEW_MATRIX, mat.getArray());
*/
matrix4x4 mat; mat.OpenGL_Matrix( OpenGLMatrices.data_array( GL_MODELVIEW ) );
// kąt między kierunkiem światła a współrzędnymi kamery // kąt między kierunkiem światła a współrzędnymi kamery
vector3 gdzie = mat * vector3(0, 0, 0); // pozycja punktu świecącego względem kamery vector3 gdzie = mat * vector3(0, 0, 0); // pozycja punktu świecącego względem kamery
fCosViewAngle = DotProduct(Normalize(mat * vector3(0, 0, 1) - gdzie), Normalize(gdzie)); fCosViewAngle = DotProduct(Normalize(mat * vector3(0, 0, 1) - gdzie), Normalize(gdzie));
@@ -2016,8 +2024,6 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, float8 *v,
pName = ""; pName = "";
if (iTexture > 0) if (iTexture > 0)
{ // obsługa stałej tekstury { // obsługa stałej tekstury
// TextureID=TTexturesManager::GetTextureID(t->String(TextureID));
// asTexture=AnsiString(t->String(iTexture));
pTexture = t->at(iTexture); pTexture = t->at(iTexture);
if (pTexture.find_last_of("/\\") == std::string::npos) if (pTexture.find_last_of("/\\") == std::string::npos)
pTexture.insert(0, Global::asCurrentTexturePath); pTexture.insert(0, Global::asCurrentTexturePath);
@@ -2029,9 +2035,17 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, float8 *v,
} }
else else
TextureID = iTexture; TextureID = iTexture;
b_aAnim = b_Anim; // skopiowanie animacji do drugiego cyklu b_aAnim = b_Anim; // skopiowanie animacji do drugiego cyklu
iFlags &= ~0x0200; // wczytano z pliku binarnego (nie jest właścicielem
// tablic) if( (eType == TP_FREESPOTLIGHT) && (iFlags & 0x10)) {
// we've added light glare which needs to be rendered during transparent phase,
// but models converted to e3d before addition won't have the render flag set correctly for this
// so as a workaround we're doing it here manually
iFlags |= 0x20;
}
iFlags &= ~0x0200; // wczytano z pliku binarnego (nie jest właścicielem tablic)
iVboPtr = tVboPtr; iVboPtr = tVboPtr;
Vertices = v + iVboPtr; Vertices = v + iVboPtr;
// if (!iNumVerts) eType=-1; //tymczasowo zmiana typu, żeby się nie // if (!iNumVerts) eType=-1; //tymczasowo zmiana typu, żeby się nie

View File

@@ -182,8 +182,7 @@ private:
int iFarAttenDecay; // ta zmienna okresla typ zaniku natezenia swiatla (0:brak, 1,2: potega 1/R) int iFarAttenDecay; // ta zmienna okresla typ zaniku natezenia swiatla (0:brak, 1,2: potega 1/R)
float fFarDecayRadius; // normalizacja j.w. float fFarDecayRadius; // normalizacja j.w.
float fCosFalloffAngle; // cosinus kąta stożka pod którym widać światło float fCosFalloffAngle; // cosinus kąta stożka pod którym widać światło
float fCosHotspotAngle; // cosinus kąta stożka pod którym widać aureolę i zwiększone natężenie float fCosHotspotAngle; // cosinus kąta stożka pod którym widać aureolę i zwiększone natężenie światła
// światła
float fCosViewAngle; // cos kata pod jakim sie teraz patrzy float fCosViewAngle; // cos kata pod jakim sie teraz patrzy
TSubModel *Next; TSubModel *Next;
@@ -256,9 +255,11 @@ public:
void SetRotateIK1(float3 vNewAngles); void SetRotateIK1(float3 vNewAngles);
TSubModel * GetFromName(std::string const &search, bool i = true); TSubModel * GetFromName(std::string const &search, bool i = true);
TSubModel * GetFromName(char const *search, bool i = true); TSubModel * GetFromName(char const *search, bool i = true);
#ifdef EU07_USE_OLD_RENDERCODE
void RenderDL(); void RenderDL();
void RenderAlphaDL(); void RenderAlphaDL();
void RenderVBO(); #endif
void RenderVBO();
void RenderAlphaVBO(); void RenderAlphaVBO();
// inline matrix4x4* GetMatrix() {return dMatrix;}; // inline matrix4x4* GetMatrix() {return dMatrix;};
inline float4x4 * GetMatrix() inline float4x4 * GetMatrix()

View File

@@ -1153,7 +1153,6 @@ TWorld::Render_Cab() {
// ABu: Rendering kabiny jako ostatniej, zeby bylo widac przez szyby, tylko w widoku ze srodka // ABu: Rendering kabiny jako ostatniej, zeby bylo widac przez szyby, tylko w widoku ze srodka
return; return;
} }
/* /*
// ABu: Rendering kabiny jako ostatniej, zeby bylo widac przez szyby, tylko w widoku ze srodka // ABu: Rendering kabiny jako ostatniej, zeby bylo widac przez szyby, tylko w widoku ze srodka
if( ( Train->Dynamic()->mdKabina != Train->Dynamic()->mdModel ) && if( ( Train->Dynamic()->mdKabina != Train->Dynamic()->mdModel ) &&

View File

@@ -139,14 +139,15 @@ class matrix4x4
// the column increasing fastest. However, some APIs (OpenGL in particular) do this // the column increasing fastest. However, some APIs (OpenGL in particular) do this
// backwards, hence the "constructor" from C matrices, or from OpenGL matrices. // backwards, hence the "constructor" from C matrices, or from OpenGL matrices.
// Note that matrices are stored internally in OpenGL format. // Note that matrices are stored internally in OpenGL format.
void C_Matrix(scalar_t *initArray) void C_Matrix(scalar_t const *initArray)
{ {
int i = 0; int i = 0;
for (int y = 0; y < 4; ++y) for (int y = 0; y < 4; ++y)
for (int x = 0; x < 4; ++x) for (int x = 0; x < 4; ++x)
(*this)(x)[y] = initArray[i++]; (*this)(x)[y] = initArray[i++];
} }
void OpenGL_Matrix(scalar_t *initArray) template <typename _Type>
void OpenGL_Matrix(_Type const *initArray)
{ {
int i = 0; int i = 0;
for (int x = 0; x < 4; ++x) for (int x = 0; x < 4; ++x)

View File

@@ -11,10 +11,19 @@ http://mozilla.org/MPL/2.0/.
#include "frustum.h" #include "frustum.h"
void void
cFrustum::calculate( glm::mat4 &Projection, glm::mat4 &Modelview ) { cFrustum::calculate() {
float *proj = &Projection[ 0 ][ 0 ]; auto const &projection = OpenGLMatrices.data( GL_PROJECTION );
float *modl = &Modelview[ 0 ][ 0 ]; auto const &modelview = OpenGLMatrices.data( GL_MODELVIEW );
calculate( projection, modelview );
}
void
cFrustum::calculate( glm::mat4 const &Projection, glm::mat4 const &Modelview ) {
float const *proj = &Projection[ 0 ][ 0 ];
float const *modl = &Modelview[ 0 ][ 0 ];
float clip[ 16 ]; float clip[ 16 ];
// multiply the matrices to retrieve clipping planes // multiply the matrices to retrieve clipping planes

View File

@@ -21,8 +21,10 @@ public:
// methods: // methods:
// update the frustum to match current view orientation // update the frustum to match current view orientation
void
calculate();
void void
calculate(glm::mat4 &Projection, glm::mat4 &Modelview); calculate(glm::mat4 const &Projection, glm::mat4 const &Modelview);
// returns true if specified point is inside of the frustum // returns true if specified point is inside of the frustum
inline inline
bool bool

View File

@@ -207,6 +207,9 @@
<ClCompile Include="uilayer.cpp"> <ClCompile Include="uilayer.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="glwidgetlibrary.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Globals.h"> <ClInclude Include="Globals.h">
@@ -401,6 +404,12 @@
<ClInclude Include="uilayer.h"> <ClInclude Include="uilayer.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="glwidgetlibrary.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="openglmatrixstack.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="maszyna.rc"> <ResourceCompile Include="maszyna.rc">

183
openglmatrixstack.h Normal file
View File

@@ -0,0 +1,183 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <stack>
#include <vector>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "GL/glew.h"
#ifdef _WINDOWS
#include "GL/wglew.h"
#endif
// encapsulation of the fixed pipeline opengl matrix stack
class opengl_matrices {
// types:
class opengl_stack {
public:
// constructors:
opengl_stack() { m_stack.emplace(1.0f); }
// methods:
glm::mat4 const &
data() const { return m_stack.top(); }
void
push_matrix() { m_stack.emplace(m_stack.top()); }
void
pop_matrix() {
m_stack.pop();
if( m_stack.empty() ) { m_stack.emplace(1.0f); }
upload(); }
void
load_identity() {
m_stack.top() = glm::mat4( 1.0f );
upload(); }
void
rotate( float const Angle, glm::vec3 const &Axis ) {
m_stack.top() = glm::rotate( m_stack.top(), Angle, Axis );
upload(); }
void
translate( glm::vec3 const &Translation ) {
m_stack.top() = glm::translate( m_stack.top(), Translation );
upload(); }
void
multiply( glm::mat4 const &Matrix ) {
m_stack.top() *= Matrix;
upload(); }
void
perspective( float const Fovy, float const Aspect, float const Znear, float const Zfar ) {
m_stack.top() *= glm::perspective( Fovy, Aspect, Znear, Zfar );
upload(); }
void
look_at( glm::vec3 const &Eye, glm::vec3 const &Center, glm::vec3 const &Up ) {
m_stack.top() *= glm::lookAt( Eye, Center, Up );
upload(); }
private:
// types:
typedef std::stack<glm::mat4> mat4_stack;
// methods:
void
upload() { ::glLoadMatrixf( &m_stack.top()[0][0] ); }
// members:
mat4_stack m_stack;
};
enum stack_mode { gl_projection = 0, gl_modelview = 1 };
typedef std::vector<opengl_stack> openglstack_array;
public:
// constructors:
opengl_matrices() {
m_stacks.emplace_back(); // projection
m_stacks.emplace_back(); // modelview
}
// methods:
void
mode( GLuint const Mode ) {
switch( Mode ) {
case GL_PROJECTION: { m_mode = stack_mode::gl_projection; break; }
case GL_MODELVIEW: { m_mode = stack_mode::gl_modelview; break; }
default: { break; } }
glMatrixMode( Mode ); }
glm::mat4 const &
data( GLuint const Mode = -1 ) const {
switch( Mode ) {
case GL_PROJECTION: { return m_stacks[ stack_mode::gl_projection ].data(); }
case GL_MODELVIEW: { return m_stacks[ stack_mode::gl_modelview ].data(); }
default: { return m_stacks[ m_mode ].data(); } } }
float const *
data_array( GLuint const Mode = -1 ) const {
return glm::value_ptr( data( Mode ) ); }
void
push_matrix() { m_stacks[ m_mode ].push_matrix(); }
void
pop_matrix() { m_stacks[ m_mode ].pop_matrix(); }
void
load_identity() { m_stacks[ m_mode ].load_identity(); }
template <typename _Type>
void
rotate( _Type const Angle, _Type const X, _Type const Y, _Type const Z ) {
m_stacks[ m_mode ].rotate(
static_cast<float>(Angle) * 0.0174532925f, // deg2rad
glm::vec3(
static_cast<float>(X),
static_cast<float>(Y),
static_cast<float>(Z) ) ); }
template <typename _Type>
void
translate( _Type const X, _Type const Y, _Type const Z ) {
m_stacks[ m_mode ].translate(
glm::vec3(
static_cast<float>( X ),
static_cast<float>( Y ),
static_cast<float>( Z ) ) ); }
template <typename _Type>
void
multiply( _Type const *Matrix ) {
m_stacks[ m_mode ].multiply(
glm::make_mat4( Matrix ) ); }
template <typename _Type>
void
perspective( _Type const Fovy, _Type const Aspect, _Type const Znear, _Type const Zfar ) {
m_stacks[ m_mode ].perspective(
static_cast<float>( Fovy ),
static_cast<float>( Aspect ),
static_cast<float>( Znear ),
static_cast<float>( Zfar ) ); }
template <typename _Type>
void
look_at( _Type const Eyex, _Type const Eyey, _Type const Eyez, _Type const Centerx, _Type const Centery, _Type const Centerz, _Type const Upx, _Type const Upy, _Type const Upz ) {
m_stacks[ m_mode ].look_at(
glm::vec3(
static_cast<float>( Eyex ),
static_cast<float>( Eyey ),
static_cast<float>( Eyez ) ),
glm::vec3(
static_cast<float>( Centerx ),
static_cast<float>( Centery ),
static_cast<float>( Centerz ) ),
glm::vec3(
static_cast<float>( Upx ),
static_cast<float>( Upy ),
static_cast<float>( Upz ) ) ); }
private:
// members:
stack_mode m_mode{ stack_mode::gl_projection };
openglstack_array m_stacks;
};
extern opengl_matrices OpenGLMatrices;
// NOTE: standard opengl calls re-definitions
#define glMatrixMode OpenGLMatrices.mode
#define glPushMatrix OpenGLMatrices.push_matrix
#define glPopMatrix OpenGLMatrices.pop_matrix
#define glLoadIdentity OpenGLMatrices.load_identity
#define glRotated OpenGLMatrices.rotate
#define glRotatef OpenGLMatrices.rotate
#define glTranslated OpenGLMatrices.translate
#define glTranslatef OpenGLMatrices.translate
// NOTE: no scale override as we aren't using it anywhere
#define glMultMatrixd OpenGLMatrices.multiply
#define glMultMatrixf OpenGLMatrices.multiply
#define gluPerspective OpenGLMatrices.perspective
#define gluLookAt OpenGLMatrices.look_at
//---------------------------------------------------------------------------

View File

@@ -15,8 +15,11 @@ http://mozilla.org/MPL/2.0/.
#include "dynobj.h" #include "dynobj.h"
#include "uilayer.h" #include "uilayer.h"
#include "logs.h" #include "logs.h"
#include "usefull.h"
#include "glwidgetlibrary.h"
opengl_renderer GfxRenderer; opengl_renderer GfxRenderer;
opengl_matrices OpenGLMatrices;
extern TWorld World; extern TWorld World;
// returns true if specified object is within camera frustum, false otherwise // returns true if specified object is within camera frustum, false otherwise
@@ -115,6 +118,8 @@ opengl_renderer::Init( GLFWwindow *Window ) {
m_lights.emplace_back( light ); m_lights.emplace_back( light );
} }
// preload some common textures
m_glaretextureid = GetTextureId( "fx\\lightglare", szTexturePath );
return true; return true;
} }
@@ -128,22 +133,31 @@ opengl_renderer::Render() {
::glDepthFunc( GL_LEQUAL ); ::glDepthFunc( GL_LEQUAL );
::glMatrixMode( GL_PROJECTION ); // select the Projection Matrix ::glMatrixMode( GL_PROJECTION ); // select the Projection Matrix
::gluPerspective(
Global::FieldOfView / Global::ZoomFactor * 0.0174532925f,
std::max( 1.0f, (float)Global::ScreenWidth ) / std::max( 1.0f, (float)Global::ScreenHeight ),
0.1f * Global::ZoomFactor,
m_drawrange * Global::fDistanceFactor );
/*
glm::mat4 projection = glm::perspective( glm::mat4 projection = glm::perspective(
Global::FieldOfView / Global::ZoomFactor * 0.0174532925f, Global::FieldOfView / Global::ZoomFactor * 0.0174532925f,
std::max( 1.0f, (float)Global::ScreenWidth ) / std::max( 1.0f, (float)Global::ScreenHeight ), std::max( 1.0f, (float)Global::ScreenWidth ) / std::max( 1.0f, (float)Global::ScreenHeight ),
0.1f * Global::ZoomFactor, 0.1f * Global::ZoomFactor,
m_drawrange * Global::fDistanceFactor ); m_drawrange * Global::fDistanceFactor );
::glLoadMatrixf( &projection[0][0] ); ::glLoadMatrixf( &projection[0][0] );
*/
::glMatrixMode( GL_MODELVIEW ); // Select The Modelview Matrix ::glMatrixMode( GL_MODELVIEW ); // Select The Modelview Matrix
glm::mat4 modelview( 1.0f );
::glLoadIdentity(); ::glLoadIdentity();
if( World.InitPerformed() ) { if( World.InitPerformed() ) {
/*
glm::mat4 modelview( 1.0f );
World.Camera.SetMatrix( modelview ); World.Camera.SetMatrix( modelview );
::glLoadMatrixf( &modelview[ 0 ][ 0 ] ); ::glLoadMatrixf( &modelview[ 0 ][ 0 ] );
m_camera.update_frustum( projection, modelview ); m_camera.update_frustum( projection, modelview );
*/
World.Camera.SetMatrix();
m_camera.update_frustum();
if( !Global::bWireFrame ) { if( !Global::bWireFrame ) {
// bez nieba w trybie rysowania linii // bez nieba w trybie rysowania linii
@@ -318,7 +332,7 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, double
nullptr ), nullptr ),
alpha ); alpha );
Model->Root->RenderDL(); Render( Model->Root );
return true; return true;
} }
@@ -342,6 +356,85 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, Math3D:
return result; return result;
} }
void
opengl_renderer::Render( TSubModel *Submodel ) {
// główna procedura renderowania przez DL
if( ( Submodel->iVisible )
&& ( TSubModel::fSquareDist >= ( Submodel->fSquareMinDist / Global::fDistanceFactor ) )
&& ( TSubModel::fSquareDist <= ( Submodel->fSquareMaxDist * Global::fDistanceFactor ) ) ) {
if( Submodel->iFlags & 0xC000 ) {
::glPushMatrix();
if( Submodel->fMatrix )
::glMultMatrixf( Submodel->fMatrix->readArray() );
if( Submodel->b_Anim )
Submodel->RaAnimation( Submodel->b_Anim );
}
if( Submodel->eType < TP_ROTATOR ) { // renderowanie obiektów OpenGL
if( Submodel->iAlpha & Submodel->iFlags & 0x1F ) // rysuj gdy element nieprzezroczysty
{
if( Submodel->TextureID < 0 ) // && (ReplacableSkinId!=0))
{ // zmienialne skóry
GfxRenderer.Bind( Submodel->ReplacableSkinId[ -Submodel->TextureID ] );
// TexAlpha=!(iAlpha&1); //zmiana tylko w przypadku wymienej tekstury
}
else
GfxRenderer.Bind( Submodel->TextureID ); // również 0
if( Global::fLuminance < Submodel->fLight ) {
::glMaterialfv( GL_FRONT, GL_EMISSION, Submodel->f4Diffuse ); // zeby swiecilo na kolorowo
::glCallList( Submodel->uiDisplayList ); // tylko dla siatki
float4 const noemission( 0.0f, 0.0f, 0.0f, 1.0f );
::glMaterialfv( GL_FRONT, GL_EMISSION, &noemission.x );
}
else
::glCallList( Submodel->uiDisplayList ); // tylko dla siatki
}
}
else if( Submodel->eType == TP_FREESPOTLIGHT ) {
// wersja DL
/*
matrix4x4 modelview;
::glGetDoublev( GL_MODELVIEW_MATRIX, modelview.getArray() );
*/
matrix4x4 modelview; modelview.OpenGL_Matrix( OpenGLMatrices.data_array( GL_MODELVIEW ) );
// kąt między kierunkiem światła a współrzędnymi kamery
auto const lightcenter = modelview * vector3( 0.0, 0.0, 0.0 ); // pozycja punktu świecącego względem kamery
Submodel->fCosViewAngle = DotProduct( Normalize( modelview * vector3( 0.0, 0.0, -1.0 ) - lightcenter ), Normalize( -lightcenter ) );
if( Submodel->fCosViewAngle > Submodel->fCosFalloffAngle ) // kąt większy niż maksymalny stożek swiatła
{
double Distdimm = 1.0;
if( Submodel->fCosViewAngle < Submodel->fCosHotspotAngle ) // zmniejszona jasność między Hotspot a Falloff
if( Submodel->fCosFalloffAngle < Submodel->fCosHotspotAngle )
Distdimm = 1.0 - ( Submodel->fCosHotspotAngle - Submodel->fCosViewAngle ) / ( Submodel->fCosHotspotAngle - Submodel->fCosFalloffAngle );
::glColor3f( Submodel->f4Diffuse[ 0 ] * Distdimm, Submodel->f4Diffuse[ 1 ] * Distdimm, Submodel->f4Diffuse[ 2 ] * Distdimm );
::glCallList( Submodel->uiDisplayList ); // wyświetlenie warunkowe
}
}
else if( Submodel->eType == TP_STARS ) {
// glDisable(GL_LIGHTING); //Tolaris-030603: bo mu punkty swiecace sie blendowaly
if( Global::fLuminance < Submodel->fLight ) {
::glMaterialfv( GL_FRONT, GL_EMISSION, Submodel->f4Diffuse ); // zeby swiecilo na kolorowo
::glCallList( Submodel->uiDisplayList ); // narysuj naraz wszystkie punkty z DL
float4 const noemission( 0.0f, 0.0f, 0.0f, 1.0f );
::glMaterialfv( GL_FRONT, GL_EMISSION, &noemission.x );
}
}
if( Submodel->Child != NULL )
if( Submodel->iAlpha & Submodel->iFlags & 0x001F0000 )
Render( Submodel->Child );
if( Submodel->iFlags & 0xC000 )
::glPopMatrix();
}
if( Submodel->b_Anim < at_SecondsJump )
Submodel->b_Anim = at_None; // wyłączenie animacji dla kolejnego użycia subm
if( Submodel->Next )
if( Submodel->iAlpha & Submodel->iFlags & 0x1F000000 )
Render( Submodel->Next ); // dalsze rekurencyjnie
};
bool bool
opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) { opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
@@ -450,7 +543,7 @@ opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, d
nullptr ), nullptr ),
alpha ); alpha );
Model->Root->RenderAlphaDL(); Render_Alpha( Model->Root );
return true; return true;
} }
@@ -473,6 +566,141 @@ opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, M
return result; return result;
} }
void
opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
// renderowanie przezroczystych przez DL
if( ( Submodel->iVisible )
&& ( TSubModel::fSquareDist >= ( Submodel->fSquareMinDist / Global::fDistanceFactor ) )
&& ( TSubModel::fSquareDist <= ( Submodel->fSquareMaxDist * Global::fDistanceFactor ) ) ) {
if( Submodel->iFlags & 0xC000 ) {
::glPushMatrix();
if( Submodel->fMatrix )
::glMultMatrixf( Submodel->fMatrix->readArray() );
if( Submodel->b_aAnim )
Submodel->RaAnimation( Submodel->b_aAnim );
}
if( Submodel->eType < TP_ROTATOR ) { // renderowanie obiektów OpenGL
if( Submodel->iAlpha & Submodel->iFlags & 0x2F ) // rysuj gdy element przezroczysty
{
if( Submodel->TextureID < 0 ) // && (ReplacableSkinId!=0))
{ // zmienialne skóry
GfxRenderer.Bind( Submodel->ReplacableSkinId[ -Submodel->TextureID ] );
// TexAlpha=iAlpha&1; //zmiana tylko w przypadku wymienej tekstury
}
else
GfxRenderer.Bind( Submodel->TextureID ); // również 0
if( Global::fLuminance < Submodel->fLight ) {
::glMaterialfv( GL_FRONT, GL_EMISSION, Submodel->f4Diffuse ); // zeby swiecilo na kolorowo
::glCallList( Submodel->uiDisplayList ); // tylko dla siatki
float4 const noemission( 0.0f, 0.0f, 0.0f, 1.0f );
::glMaterialfv( GL_FRONT, GL_EMISSION, &noemission.x );
}
else
::glCallList( Submodel->uiDisplayList ); // tylko dla siatki
}
}
else if( Submodel->eType == TP_FREESPOTLIGHT ) {
// dorobić aureolę!
if( Global::fLuminance < Submodel->fLight ) {
// NOTE: we're forced here to redo view angle calculations etc, because this data isn't instanced but stored along with the single mesh
// TODO: separate instance data from reusable geometry
/*
matrix4x4 modelview;
::glGetDoublev( GL_MODELVIEW_MATRIX, modelview.getArray() );
*/
/*
matrix4x4 modelview; modelview.OpenGL_Matrix( OpenGLMatrices.data_array( GL_MODELVIEW ) );
// kąt między kierunkiem światła a współrzędnymi kamery
auto const lightcenter = modelview * vector3( 0.0, 0.0, -0.05 ); // pozycja punktu świecącego względem kamery
Submodel->fCosViewAngle = DotProduct( Normalize( modelview * vector3( 0.0, 0.0, -1.0 ) - lightcenter ), Normalize( -lightcenter ) );
*/
auto const &modelview = OpenGLMatrices.data( GL_MODELVIEW );
auto const lightcenter = modelview * glm::vec4( 0.0f, 0.0f, -0.05f, 1.0f ); // pozycja punktu świecącego względem kamery
Submodel->fCosViewAngle = glm::dot( glm::normalize( modelview * glm::vec4( 0.0f, 0.0f, -1.0f, 1.0f ) - lightcenter ), glm::normalize( -lightcenter ) );
float fadelevel = 0.5f;
if( ( Submodel->fCosViewAngle > 0.0 ) && ( Submodel->fCosViewAngle > Submodel->fCosFalloffAngle ) ) {
fadelevel *= ( Submodel->fCosViewAngle - Submodel->fCosFalloffAngle ) / ( 1.0 - Submodel->fCosFalloffAngle );
::glPushAttrib( GL_ENABLE_BIT | GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT );
Bind( m_glaretextureid );
::glColor4f( Submodel->f4Diffuse[ 0 ], Submodel->f4Diffuse[ 1 ], Submodel->f4Diffuse[ 2 ], fadelevel );
::glDisable( GL_LIGHTING );
::glBlendFunc( GL_SRC_ALPHA, GL_ONE );
::glPushMatrix();
::glLoadIdentity(); // macierz jedynkowa
::glTranslatef( lightcenter.x, lightcenter.y, lightcenter.z ); // początek układu zostaje bez zmian
::glRotated( atan2( lightcenter.x, lightcenter.z ) * 180.0 / M_PI, 0.0, 1.0, 0.0 ); // jedynie obracamy w pionie o kąt
::glMaterialfv( GL_FRONT, GL_EMISSION, Submodel->f4Diffuse ); // zeby swiecilo na kolorowo
::glBegin( GL_TRIANGLE_STRIP );
float const size = 2.5f;
::glTexCoord2f( 1.0f, 1.0f ); ::glVertex3f( -size, size, 0.0f );
::glTexCoord2f( 0.0f, 1.0f ); ::glVertex3f( size, size, 0.0f );
::glTexCoord2f( 1.0f, 0.0f ); ::glVertex3f( -size, -size, 0.0f );
::glTexCoord2f( 0.0f, 0.0f ); ::glVertex3f( size, -size, 0.0f );
/*
// NOTE: we could do simply...
vec3 vertexPosition_worldspace =
particleCenter_wordspace
+ CameraRight_worldspace * squareVertices.x * BillboardSize.x
+ CameraUp_worldspace * squareVertices.y * BillboardSize.y;
// ...etc instead IF we had easy access to camera's forward and right vectors. TODO: check if Camera matrix is accessible
*/
::glEnd();
float4 const noemission( 0.0f, 0.0f, 0.0f, 1.0f );
::glMaterialfv( GL_FRONT, GL_EMISSION, &noemission.x );
::glPopMatrix();
::glPopAttrib();
}
}
}
if( Submodel->Child != NULL ) {
if( Submodel->eType == TP_TEXT ) { // tekst renderujemy w specjalny sposób, zamiast submodeli z łańcucha Child
int i, j = (int)Submodel->pasText->size();
TSubModel *p;
if( !Submodel->smLetter ) { // jeśli nie ma tablicy, to ją stworzyć; miejsce nieodpowiednie, ale tymczasowo może być
Submodel->smLetter = new TSubModel *[ 256 ]; // tablica wskaźników submodeli dla wyświetlania tekstu
::ZeroMemory( Submodel->smLetter, 256 * sizeof( TSubModel * ) ); // wypełnianie zerami
p = Submodel->Child;
while( p ) {
Submodel->smLetter[ p->pName[ 0 ] ] = p;
p = p->Next; // kolejny znak
}
}
for( i = 1; i <= j; ++i ) {
p = Submodel->smLetter[ ( *( Submodel->pasText) )[ i ] ]; // znak do wyświetlenia
if( p ) { // na razie tylko jako przezroczyste
Render_Alpha( p );
if( p->fMatrix )
::glMultMatrixf( p->fMatrix->readArray() ); // przesuwanie widoku
}
}
}
else if( Submodel->iAlpha & Submodel->iFlags & 0x002F0000 )
Render_Alpha( Submodel->Child );
}
if( Submodel->iFlags & 0xC000 )
::glPopMatrix();
}
if( Submodel->b_aAnim < at_SecondsJump )
Submodel->b_aAnim = at_None; // wyłączenie animacji dla kolejnego użycia submodelu
if( Submodel->Next != NULL )
if( Submodel->iAlpha & Submodel->iFlags & 0x2F000000 )
Render_Alpha( Submodel->Next );
};
#endif #endif
void void

View File

@@ -89,6 +89,9 @@ class opengl_camera {
public: public:
// methods: // methods:
inline inline
void
update_frustum() { m_frustum.calculate(); }
inline
void void
update_frustum(glm::mat4 &Projection, glm::mat4 &Modelview) { m_frustum.calculate(Projection, Modelview); } update_frustum(glm::mat4 &Projection, glm::mat4 &Modelview) { m_frustum.calculate(Projection, Modelview); }
bool bool
@@ -122,12 +125,16 @@ public:
Render( TModel3d *Model, material_data const *Material, double const Squaredistance ); Render( TModel3d *Model, material_data const *Material, double const Squaredistance );
bool bool
Render( TModel3d *Model, material_data const *Material, Math3D::vector3 const &Position, Math3D::vector3 const &Angle ); Render( TModel3d *Model, material_data const *Material, Math3D::vector3 const &Position, Math3D::vector3 const &Angle );
void
Render( TSubModel *Submodel );
bool bool
Render_Alpha( TDynamicObject *Dynamic ); Render_Alpha( TDynamicObject *Dynamic );
bool bool
Render_Alpha( TModel3d *Model, material_data const *Material, double const Squaredistance ); Render_Alpha( TModel3d *Model, material_data const *Material, double const Squaredistance );
bool bool
Render_Alpha( TModel3d *Model, material_data const *Material, Math3D::vector3 const &Position, Math3D::vector3 const &Angle ); Render_Alpha( TModel3d *Model, material_data const *Material, Math3D::vector3 const &Position, Math3D::vector3 const &Angle );
void
Render_Alpha( TSubModel *Submodel );
#endif #endif
// maintenance jobs // maintenance jobs
void void
@@ -185,6 +192,7 @@ private:
double m_updateaccumulator{ 0.0 }; double m_updateaccumulator{ 0.0 };
std::string m_debuginfo; std::string m_debuginfo;
GLFWwindow *m_window{ nullptr }; GLFWwindow *m_window{ nullptr };
texture_manager::size_type m_glaretextureid{ -1 };
}; };
extern opengl_renderer GfxRenderer; extern opengl_renderer GfxRenderer;

View File

@@ -18,7 +18,7 @@ cStars::render() {
::glPushMatrix(); ::glPushMatrix();
::glRotatef( m_latitude, 1.0f, 0.0f, 0.0f ); // ustawienie osi OY na północ ::glRotatef( m_latitude, 1.0f, 0.0f, 0.0f ); // ustawienie osi OY na północ
::glRotatef( -std::fmod( Global::fTimeAngleDeg, 360.0f ), 0.0f, 1.0f, 0.0f ); // obrót dobowy osi OX ::glRotatef( -std::fmod( (float)Global::fTimeAngleDeg, 360.0f ), 0.0f, 1.0f, 0.0f ); // obrót dobowy osi OX
::glPointSize( 2.0f ); ::glPointSize( 2.0f );
if( Global::bUseVBO ) { if( Global::bUseVBO ) {

View File

@@ -83,3 +83,5 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include "openglmatrixstack.h"