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

View File

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

View File

@@ -571,7 +571,11 @@ void TGroundNode::RenderDL()
{ // obiekty renderowane niezależnie od odległości
case TP_SUBMODEL:
TSubModel::fSquareDist = 0;
#ifdef EU07_USE_OLD_RENDERCODE
return smTerrain->RenderDL();
#else
GfxRenderer.Render( smTerrain );
#endif
}
// if (pTriGroup) if (pTriGroup!=this) return; //wyświetla go inny obiekt
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));
fCosHotspotAngle = cos(DegToRad(0.5 * fCosHotspotAngle));
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)
{
@@ -967,9 +969,9 @@ void TSubModel::RaAnimation(TAnimType a)
if (iAnimOwner != iInstance)
break; // cudza animacja
glTranslatef(v_TransVector.x, v_TransVector.y, v_TransVector.z);
glRotatef(v_Angles.x, 1.0, 0.0, 0.0);
glRotatef(v_Angles.y, 0.0, 1.0, 0.0);
glRotatef(v_Angles.z, 0.0, 0.0, 1.0);
glRotatef(v_Angles.x, 1.0f, 0.0f, 0.0f);
glRotatef(v_Angles.y, 0.0f, 1.0f, 0.0f);
glRotatef(v_Angles.z, 0.0f, 0.0f, 1.0f);
break;
case at_SecondsJump: // sekundy z przeskokiem
glRotatef(floor(GlobalTime->mr) * 6.0, 0.0, 1.0, 0.0);
@@ -999,11 +1001,13 @@ void TSubModel::RaAnimation(TAnimType a)
break;
case at_Billboard: // obrót w pionie do kamery
{
/*
matrix4x4 mat; // potrzebujemy współrzędne przesunięcia środka układu
// współrzędnych submodelu
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
glTranslatef(gdzie.x, gdzie.y, gdzie.z); // początek układu zostaje bez
// 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
break;
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
// (azymut)
glRotatef(v_Angles.x, 1.0, 0.0, 0.0); // obrót względem poziomu (deklinacja)
glRotatef(v_Angles.z, 0.0f, 1.0f, 0.0f); // obrót względem osi pionowej (azymut)
glRotatef(v_Angles.x, 1.0f, 0.0f, 0.0f); // obrót względem poziomu (deklinacja)
break;
case at_DigiClk: // animacja zegara cyfrowego
{ // ustawienie animacji w submodelach potomnych
@@ -1048,6 +1051,7 @@ void TSubModel::RaAnimation(TAnimType a)
}
};
#ifdef EU07_USE_OLD_RENDERCODE
void TSubModel::RenderDL()
{ // główna procedura renderowania przez DL
if( ( iVisible )
@@ -1228,6 +1232,7 @@ void TSubModel::RenderAlphaDL()
if (iAlpha & iFlags & 0x2F000000)
Next->RenderAlphaDL();
}; // RenderAlpha
#endif
void TSubModel::RenderVBO()
{ // główna procedura renderowania przez VBO
@@ -1271,8 +1276,11 @@ void TSubModel::RenderVBO()
}
else if (eType == TP_FREESPOTLIGHT)
{ // wersja VBO
/*
matrix4x4 mat; // macierz opisuje układ renderowania względem kamery
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
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));
@@ -2016,8 +2024,6 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, float8 *v,
pName = "";
if (iTexture > 0)
{ // obsługa stałej tekstury
// TextureID=TTexturesManager::GetTextureID(t->String(TextureID));
// asTexture=AnsiString(t->String(iTexture));
pTexture = t->at(iTexture);
if (pTexture.find_last_of("/\\") == std::string::npos)
pTexture.insert(0, Global::asCurrentTexturePath);
@@ -2029,9 +2035,17 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, float8 *v,
}
else
TextureID = iTexture;
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;
Vertices = v + iVboPtr;
// 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)
float fFarDecayRadius; // normalizacja j.w.
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
// światła
float fCosHotspotAngle; // cosinus kąta stożka pod którym widać aureolę i zwiększone natężenie światła
float fCosViewAngle; // cos kata pod jakim sie teraz patrzy
TSubModel *Next;
@@ -256,9 +255,11 @@ public:
void SetRotateIK1(float3 vNewAngles);
TSubModel * GetFromName(std::string const &search, bool i = true);
TSubModel * GetFromName(char const *search, bool i = true);
#ifdef EU07_USE_OLD_RENDERCODE
void RenderDL();
void RenderAlphaDL();
void RenderVBO();
#endif
void RenderVBO();
void RenderAlphaVBO();
// inline matrix4x4* GetMatrix() {return dMatrix;};
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
return;
}
/*
// ABu: Rendering kabiny jako ostatniej, zeby bylo widac przez szyby, tylko w widoku ze srodka
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
// backwards, hence the "constructor" from C matrices, or from OpenGL matrices.
// 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;
for (int y = 0; y < 4; ++y)
for (int x = 0; x < 4; ++x)
(*this)(x)[y] = initArray[i++];
}
void OpenGL_Matrix(scalar_t *initArray)
template <typename _Type>
void OpenGL_Matrix(_Type const *initArray)
{
int i = 0;
for (int x = 0; x < 4; ++x)

View File

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

View File

@@ -21,8 +21,10 @@ public:
// methods:
// update the frustum to match current view orientation
void
calculate();
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
inline
bool

View File

@@ -207,6 +207,9 @@
<ClCompile Include="uilayer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="glwidgetlibrary.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Globals.h">
@@ -401,6 +404,12 @@
<ClInclude Include="uilayer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="glwidgetlibrary.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="openglmatrixstack.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<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 "uilayer.h"
#include "logs.h"
#include "usefull.h"
#include "glwidgetlibrary.h"
opengl_renderer GfxRenderer;
opengl_matrices OpenGLMatrices;
extern TWorld World;
// 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 );
}
// preload some common textures
m_glaretextureid = GetTextureId( "fx\\lightglare", szTexturePath );
return true;
}
@@ -128,22 +133,31 @@ opengl_renderer::Render() {
::glDepthFunc( GL_LEQUAL );
::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(
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 );
::glLoadMatrixf( &projection[0][0] );
*/
::glMatrixMode( GL_MODELVIEW ); // Select The Modelview Matrix
glm::mat4 modelview( 1.0f );
::glLoadIdentity();
if( World.InitPerformed() ) {
/*
glm::mat4 modelview( 1.0f );
World.Camera.SetMatrix( modelview );
::glLoadMatrixf( &modelview[ 0 ][ 0 ] );
m_camera.update_frustum( projection, modelview );
*/
World.Camera.SetMatrix();
m_camera.update_frustum();
if( !Global::bWireFrame ) {
// bez nieba w trybie rysowania linii
@@ -318,7 +332,7 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, double
nullptr ),
alpha );
Model->Root->RenderDL();
Render( Model->Root );
return true;
}
@@ -342,6 +356,85 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, Math3D:
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
opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
@@ -450,7 +543,7 @@ opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, d
nullptr ),
alpha );
Model->Root->RenderAlphaDL();
Render_Alpha( Model->Root );
return true;
}
@@ -473,6 +566,141 @@ opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, M
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
void

View File

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

View File

@@ -18,7 +18,7 @@ cStars::render() {
::glPushMatrix();
::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 );
if( Global::bUseVBO ) {

View File

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