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

partial replacement of math classes with glm

This commit is contained in:
tmj-fstate
2017-06-10 22:51:51 +02:00
parent de5b245f2e
commit 22746bad21
16 changed files with 603 additions and 714 deletions

View File

@@ -631,11 +631,13 @@ TSubModel * TAnimModel::TerrainSquare(int n)
{ // pobieranie wskaźników do pierwszego submodelu
return pModel ? pModel->TerrainSquare(n) : 0;
};
#ifdef EU07_USE_OLD_RENDERCODE
void TAnimModel::TerrainRenderVBO(int n)
{ // renderowanie terenu z VBO
if (pModel)
pModel->TerrainRenderVBO(n);
};
#endif
//---------------------------------------------------------------------------
void TAnimModel::Advanced()

View File

@@ -128,8 +128,11 @@ class TAnimAdvanced
int SortByBone();
};
class TAnimModel
{ // opakowanie modelu, określające stan egzemplarza
// opakowanie modelu, określające stan egzemplarza
class TAnimModel {
friend class opengl_renderer;
private:
TAnimContainer *pRoot; // pojemniki sterujące, tylko dla aniomowanych submodeli
TModel3d *pModel;
@@ -173,7 +176,9 @@ class TAnimModel
bool TerrainLoaded();
int TerrainCount();
TSubModel * TerrainSquare(int n);
#ifdef EU07_USE_OLD_RENDERCODE
void TerrainRenderVBO(int n);
#endif
void AnimationVND(void *pData, double a, double b, double c, double d);
void LightSet(int n, float v);
static void AnimUpdate(double dt);

File diff suppressed because it is too large Load Diff

View File

@@ -23,20 +23,27 @@ http://mozilla.org/MPL/2.0/.
using namespace Math3D;
typedef int TGroundNodeType;
// Ra: zmniejszone liczby, aby zrobić tabelkę i zoptymalizować wyszukiwanie
const int TP_MODEL = 10;
/*
const int TP_MESH = 11; // Ra: specjalny obiekt grupujący siatki dla tekstury
const int TP_DUMMYTRACK = 12; // Ra: zdublowanie obiektu toru dla rozdzielenia tekstur
*/
const int TP_TERRAIN = 13; // Ra: specjalny model dla terenu
const int TP_DYNAMIC = 14;
const int TP_SOUND = 15;
const int TP_TRACK = 16;
// const int TP_GEOMETRY=17;
/*
const int TP_GEOMETRY=17;
*/
const int TP_MEMCELL = 18;
const int TP_EVLAUNCH = 19; // MC
const int TP_TRACTION = 20;
const int TP_TRACTIONPOWERSOURCE = 21; // MC
// const int TP_ISOLATED=22; //Ra
/*
const int TP_ISOLATED=22; //Ra
*/
const int TP_SUBMODEL = 22; // Ra: submodele terenu
const int TP_LAST = 25; // rozmiar tablicy
@@ -64,37 +71,28 @@ struct DaneRozkaz2
};
};
typedef int TGroundNodeType;
struct TGroundVertex
{
vector3 Point;
vector3 Normal;
float tu{ 0.0f }, tv{ 0.0f };
glm::dvec3 position;
glm::vec3 normal;
glm::vec2 texture;
void HalfSet(const TGroundVertex &v1, const TGroundVertex &v2)
{ // wyliczenie współrzędnych i mapowania punktu na środku odcinka v1<->v2
Point = 0.5 * (v1.Point + v2.Point);
Normal = 0.5 * (v1.Normal + v2.Normal);
tu = 0.5 * (v1.tu + v2.tu);
tv = 0.5 * (v1.tv + v2.tv);
interpolate_( v1, v2, 0.5 );
}
void SetByX(const TGroundVertex &v1, const TGroundVertex &v2, double x)
{ // wyliczenie współrzędnych i mapowania punktu na odcinku v1<->v2
double i = (x - v1.Point.x) / (v2.Point.x - v1.Point.x); // parametr równania
double j = 1.0 - i;
Point = j * v1.Point + i * v2.Point;
Normal = j * v1.Normal + i * v2.Normal;
tu = j * v1.tu + i * v2.tu;
tv = j * v1.tv + i * v2.tv;
interpolate_( v1, v2, ( x - v1.position.x ) / ( v2.position.x - v1.position.x ) );
}
void SetByZ(const TGroundVertex &v1, const TGroundVertex &v2, double z)
{ // wyliczenie współrzędnych i mapowania punktu na odcinku v1<->v2
double i = (z - v1.Point.z) / (v2.Point.z - v1.Point.z); // parametr równania
double j = 1.0 - i;
Point = j * v1.Point + i * v2.Point;
Normal = j * v1.Normal + i * v2.Normal;
tu = j * v1.tu + i * v2.tu;
tv = j * v1.tv + i * v2.tv;
interpolate_( v1, v2, ( z - v1.position.z ) / ( v2.position.z - v1.position.z ) );
}
void interpolate_( const TGroundVertex &v1, const TGroundVertex &v2, double factor ) {
position = interpolate( v1.position, v2.position, factor );
normal = interpolate( v1.normal, v2.normal, static_cast<float>( factor ) );
texture = interpolate( v1.texture, v2.texture, static_cast<float>( factor ) );
}
};
@@ -103,8 +101,11 @@ class TGroundNode : public Resource
friend class opengl_renderer;
private:
public:
TGroundNode *nNext; // lista wszystkich w scenerii, ostatni na początku
TGroundNode *nNext2; // lista obiektów w sektorze
TGroundNode *nNext3; // lista obiektów renderowanych we wspólnym cyklu
std::string asName; // nazwa (nie zawsze ma znaczenie)
TGroundNodeType iType; // typ obiektu
union
{ // Ra: wskażniki zależne od typu - zrobić klasy dziedziczone zamiast
@@ -112,7 +113,7 @@ public:
TSubModel *smTerrain; // modele terenu (kwadratow kilometrowych)
TAnimModel *Model; // model z animacjami
TDynamicObject *DynamicObject; // pojazd
vector3 *Points; // punkty dla linii
glm::dvec3 *Points; // punkty dla linii
TTrack *pTrack; // trajektoria ruchu
TGroundVertex *Vertices; // wierzchołki dla trójkątów
TMemCell *MemCell; // komórka pamięci
@@ -122,39 +123,35 @@ public:
TTextSound *tsStaticSound; // dźwięk przestrzenny
TGroundNode *nNode; // obiekt renderujący grupowo ma tu wskaźnik na listę obiektów
};
std::string asName; // nazwa (nie zawsze ma znaczenie)
vector3 pCenter; // współrzędne środka do przydzielenia sektora
vector3 m_rootposition; // position of the ground (sub)rectangle holding the node, in the 3d world
Math3D::vector3 pCenter; // współrzędne środka do przydzielenia sektora
glm::dvec3 m_rootposition; // position of the ground (sub)rectangle holding the node, in the 3d world
// visualization-related data
// TODO: wrap these in a struct, when cleaning objects up
double fSquareMinRadius; // kwadrat widoczności od
double fSquareRadius; // kwadrat widoczności do
union
{
int iNumVerts; // dla trójkątów
int iNumPts; // dla linii
int iCount; // dla terenu
};
double fLineThickness; // McZapkie-120702: grubosc linii
double fSquareRadius; // kwadrat widoczności do
double fSquareMinRadius; // kwadrat widoczności od
int iVersion; // wersja siatki (do wykonania rekompilacji)
// union ?
GLuint DisplayListID; // numer siatki DisplayLists
bool PROBLEND;
int iVboPtr; // indeks w buforze VBO
texture_handle TextureID; // główna (jedna) tekstura obiektu
int iFlags; // tryb przezroczystości: 0x10-nieprz.,0x20-przezroczysty,0x30-mieszany
int Ambient[4], Diffuse[4], Specular[4]; // oświetlenie
texture_handle TextureID; // główna (jedna) tekstura obiektu
glm::vec3
Ambient{ 1.0f, 1.0f, 1.0f },
Diffuse{ 1.0f, 1.0f, 1.0f },
Specular{ 1.0f, 1.0f, 1.0f }; // oświetlenie
double fLineThickness; // McZapkie-120702: grubosc linii
bool PROBLEND;
bool bVisible;
TGroundNode *nNext; // lista wszystkich w scenerii, ostatni na początku
TGroundNode *nNext2; // lista obiektów w sektorze
TGroundNode *nNext3; // lista obiektów renderowanych we wspólnym cyklu
TGroundNode();
TGroundNode(TGroundNodeType t, int n = 0);
~TGroundNode();
void Init(int n);
void InitCenter(); // obliczenie współrzędnych środka
void InitNormals();
// bool Disable();
@@ -167,19 +164,20 @@ public:
return NULL;
};
void Compile(Math3D::vector3 const &Origin, bool const Multiple = false);
void Compile(glm::dvec3 const &Origin, bool const Multiple = false);
void Release();
void RenderHidden(); // obsługa dźwięków i wyzwalaczy zdarzeń
#ifdef EU07_USE_OLD_RENDERCODE
// (McZapkie-131202)
void RaRenderVBO(); // renderowanie (nieprzezroczystych) ze wspólnego VBO
#endif
};
struct bounding_area {
glm::vec3 center; // mid point of the rectangle
float radius{ 0.0f }; // radius of the bounding sphere
float radius { 0.0f }; // radius of the bounding sphere
};
class TSubRect : public Resource, public CMesh
@@ -190,8 +188,10 @@ class TSubRect : public Resource, public CMesh
TTrack **tTracks = nullptr; // tory do renderowania pojazdów
protected:
TTrack *tTrackAnim = nullptr; // obiekty do przeliczenia animacji
#ifdef EU07_USE_OLD_RENDERCODE
TGroundNode *nRootMesh = nullptr; // obiekty renderujące wg tekstury (wtórne, lista po nNext2)
TGroundNode *nMeshed = nullptr; // lista obiektów dla których istnieją obiekty renderujące grupowo
#endif
public:
TGroundNode *nRootNode = nullptr; // wszystkie obiekty w sektorze, z wyjątkiem renderujących i pojazdów (nNext2)
TGroundNode *nRenderHidden = nullptr; // lista obiektów niewidocznych, "renderowanych" również z tyłu (nNext3)
@@ -211,10 +211,9 @@ class TSubRect : public Resource, public CMesh
virtual ~TSubRect();
virtual void Release(); // zwalnianie VBO sektora
void NodeAdd(TGroundNode *Node); // dodanie obiektu do sektora na etapie rozdzielania na sektory
void RaNodeAdd(TGroundNode *Node); // dodanie obiektu do listy renderowania
void Sort(); // optymalizacja obiektów w sektorze (sortowanie wg tekstur)
TTrack * FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude);
TTraction * FindTraction(vector3 *Point, int &iConnection, TTraction *Exclude);
TTraction * FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *Exclude);
bool StartVBO(); // ustwienie VBO sektora dla (nRenderRect), (nRenderRectAlpha) i (nRenderWires)
bool RaTrackAnimAdd(TTrack *t); // zgłoszenie toru do animacji
void RaAnimate(); // przeliczenie animacji torów
@@ -311,8 +310,8 @@ class TGround
bool InitEvents();
bool InitLaunchers();
TTrack * FindTrack(vector3 Point, int &iConnection, TGroundNode *Exclude);
TTraction * FindTraction(vector3 *Point, int &iConnection, TGroundNode *Exclude);
TTraction * TractionNearestFind(vector3 &p, int dir, TGroundNode *n);
TTraction * FindTraction(glm::dvec3 const &Point, int &iConnection, TGroundNode *Exclude);
TTraction * TractionNearestFind(glm::dvec3 &p, int dir, TGroundNode *n);
TGroundNode * AddGroundNode(cParser *parser);
void UpdatePhys(double dt, int iter); // aktualizacja fizyki stałym krokiem
bool Update(double dt, int iter); // aktualizacja przesunięć zgodna z FPS

View File

@@ -177,12 +177,19 @@ template <typename ColorT> inline void readColor(cParser &parser, ColorT *color)
color[ 2 ] /= 255.0;
};
inline void readColor(cParser &parser, int &color)
inline void readColor(cParser &parser, glm::vec4 &color)
{
int r, g, b, discard;
int discard;
parser.getTokens(4, false);
parser >> discard >> r >> g >> b;
parser
>> discard
>> color.r
>> color.g
>> color.b;
color /= 255.0f;
/*
color = r + (g << 8) + (b << 16);
*/
};
/*
inline void readMatrix(cParser& parser,matrix4x4& matrix)
@@ -620,7 +627,7 @@ int TSubModel::TriangleAdd(TModel3d *m, texture_handle tex, int tri)
return s->iNumVerts - tri; // zwraca pozycję tych trójkątów w submodelu
};
basic_vertex *TSubModel::TrianglePtr(int tex, int pos, int *la, int *ld, int *ls)
basic_vertex *TSubModel::TrianglePtr(int tex, int pos, glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular )
{ // zwraca wskaźnik do wypełnienia tabeli wierzchołków, używane
// przy tworzeniu E3D terenu
TSubModel *s = this;
@@ -639,7 +646,7 @@ basic_vertex *TSubModel::TrianglePtr(int tex, int pos, int *la, int *ld, int *ls
s->iVboPtr = iInstance; // pozycja submodelu w tabeli wierzchołków
iInstance += s->iNumVerts; // pozycja dla następnego
}
s->ColorsSet(la, ld, ls); // ustawienie kolorów świateł
s->ColorsSet(Ambient, Diffuse, Specular); // ustawienie kolorów świateł
return s->Vertices + pos; // wskaźnik na wolne miejsce w tabeli wierzchołków
};
@@ -1038,20 +1045,24 @@ void TSubModel::RaArrayFill(CVertNormTex *Vert)
{ // wypełnianie tablic VBO
if (Child)
Child->RaArrayFill(Vert);
if ((eType < TP_ROTATOR) || (eType == TP_STARS))
for (int i = 0; i < iNumVerts; ++i)
{
Vert[iVboPtr + i].x = Vertices[i].position.x;
Vert[iVboPtr + i].y = Vertices[i].position.y;
Vert[iVboPtr + i].z = Vertices[i].position.z;
Vert[iVboPtr + i].nx = Vertices[i].normal.x;
Vert[iVboPtr + i].ny = Vertices[i].normal.y;
Vert[iVboPtr + i].nz = Vertices[i].normal.z;
Vert[iVboPtr + i].u = Vertices[i].texture.s;
Vert[iVboPtr + i].v = Vertices[i].texture.t;
}
else if (eType == TP_FREESPOTLIGHT)
Vert[iVboPtr].x = Vert[iVboPtr].y = Vert[iVboPtr].z = 0.0;
if( ( eType < TP_ROTATOR ) || ( eType == TP_STARS ) )
for( int i = 0; i < iNumVerts; ++i ) {
Vert[ iVboPtr + i ].position = Vertices[ i ].position;
Vert[ iVboPtr + i ].normal = Vertices[ i ].normal;
Vert[ iVboPtr + i ].texture = Vertices[ i ].texture;
/*
Vert[iVboPtr + i].x = Vertices[i].position.x;
Vert[iVboPtr + i].y = Vertices[i].position.y;
Vert[iVboPtr + i].z = Vertices[i].position.z;
Vert[iVboPtr + i].nx = Vertices[i].normal.x;
Vert[iVboPtr + i].ny = Vertices[i].normal.y;
Vert[iVboPtr + i].nz = Vertices[i].normal.z;
Vert[iVboPtr + i].u = Vertices[i].texture.s;
Vert[iVboPtr + i].v = Vertices[i].texture.t;
*/
}
else if( eType == TP_FREESPOTLIGHT )
Vert[ iVboPtr ].position = glm::vec3();
if (Next)
Next->RaArrayFill(Vert);
};
@@ -1073,9 +1084,13 @@ void TSubModel::AdjustDist()
Next->AdjustDist();
};
void TSubModel::ColorsSet(int *a, int *d, int *s)
void TSubModel::ColorsSet( glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular )
{ // ustawienie kolorów dla modelu terenu
int i;
f4Ambient = glm::vec4( Ambient, 1.0f );
f4Diffuse = glm::vec4( Diffuse, 1.0f );
f4Specular = glm::vec4( Specular, 1.0f );
/*
int i;
if (a)
for (i = 0; i < 4; ++i)
f4Ambient[i] = a[i] / 255.0;
@@ -1085,6 +1100,7 @@ void TSubModel::ColorsSet(int *a, int *d, int *s)
if (s)
for (i = 0; i < 4; ++i)
f4Specular[i] = s[i] / 255.0;
*/
};
void TSubModel::ParentMatrix(float4x4 *m)
@@ -1429,13 +1445,13 @@ void TSubModel::deserialize(std::istream &s)
fVisible = sn_utils::ld_float32(s);
fLight = sn_utils::ld_float32(s);
for (size_t i = 0; i < 4; i++)
for (size_t i = 0; i < 4; ++i)
f4Ambient[i] = sn_utils::ld_float32(s);
for (size_t i = 0; i < 4; i++)
for (size_t i = 0; i < 4; ++i)
f4Diffuse[i] = sn_utils::ld_float32(s);
for (size_t i = 0; i < 4; i++)
for (size_t i = 0; i < 4; ++i)
f4Specular[i] = sn_utils::ld_float32(s);
for (size_t i = 0; i < 4; i++)
for (size_t i = 0; i < 4; ++i)
f4Emision[i] = sn_utils::ld_float32(s);
fWireSize = sn_utils::ld_float32(s);
@@ -1828,28 +1844,17 @@ TSubModel *TModel3d::TerrainSquare(int n)
r->UnFlagNext(); // blokowanie wyświetlania po Next głównej listy
return r;
};
#ifdef EU07_USE_OLD_RENDERCODE
void TModel3d::TerrainRenderVBO(int n)
{ // renderowanie terenu z VBO
glPushMatrix();
::glPushMatrix();
::glTranslated( -Global::pCameraPosition.x, -Global::pCameraPosition.y, -Global::pCameraPosition.z );
// glTranslated(vPosition->x,vPosition->y,vPosition->z);
// if (vAngle->y!=0.0) glRotated(vAngle->y,0.0,1.0,0.0);
// if (vAngle->x!=0.0) glRotated(vAngle->x,1.0,0.0,0.0);
// if (vAngle->z!=0.0) glRotated(vAngle->z,0.0,0.0,1.0);
// TSubModel::fSquareDist=SquareMagnitude(*vPosition-Global::GetCameraPosition());
// //zmienna globalna!
if (StartVBO())
{ // odwrócenie flag, aby wyłapać nieprzezroczyste
// Root->ReplacableSet(ReplacableSkinId,iAlpha^0x0F0F000F);
TSubModel *r = Root;
while (r)
{
if (r->iVisible == n) // tylko jeśli ma być widoczny w danej ramce (problem dla 0==false)
GfxRenderer.Render(r); // sub kolejne (Next) się nie wyrenderują
r = r->NextGet();
}
EndVBO();
}
glPopMatrix();
TSubModel *r = Root;
while( r ) {
if( r->iVisible == n ) // tylko jeśli ma być widoczny w danej ramce (problem dla 0==false)
GfxRenderer.Render( r ); // sub kolejne (Next) się nie wyrenderują
r = r->NextGet();
}
::glPopMatrix();
};
#endif

View File

@@ -92,10 +92,11 @@ private:
int iTexture; // numer nazwy tekstury, -1 wymienna, 0 brak
float fVisible; // próg jasności światła do załączenia submodelu
float fLight; // próg jasności światła do zadziałania selfillum
float f4Ambient[4];
float f4Diffuse[4]; // float ze względu na glMaterialfv()
float f4Specular[4];
float f4Emision[4];
glm::vec4
f4Ambient,
f4Diffuse,
f4Specular,
f4Emision;
float fWireSize; // nie używane, ale wczytywane
float fSquareMaxDist;
float fSquareMinDist;
@@ -156,7 +157,7 @@ public:
TSubModel * NextGet() { return Next; };
TSubModel * ChildGet() { return Child; };
int TriangleAdd(TModel3d *m, texture_handle tex, int tri);
basic_vertex * TrianglePtr(int tex, int pos, int *la, int *ld, int *ls);
basic_vertex * TrianglePtr(int tex, int pos, glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular );
void SetRotate(float3 vNewRotateAxis, float fNewAngle);
void SetRotateXYZ(vector3 vNewAngles);
void SetRotateXYZ(float3 vNewAngles);
@@ -189,7 +190,7 @@ public:
// Ra: funkcje do budowania terenu z E3D
int Flags() { return iFlags; };
void UnFlagNext() { iFlags &= 0x00FFFFFF; };
void ColorsSet(int *a, int *d, int *s);
void ColorsSet( glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular );
inline float3 Translation1Get()
{
return fMatrix ? *(fMatrix->TranslationGet()) + v_TransVector : v_TransVector;
@@ -247,7 +248,9 @@ public:
std::string NameGet() { return m_filename; };
int TerrainCount();
TSubModel * TerrainSquare(int n);
void TerrainRenderVBO(int n);
#ifdef EU07_USE_OLD_RENDERCODE
void TerrainRenderVBO(int n);
#endif
void deserialize(std::istream &s, size_t size, bool dynamic);
};

View File

@@ -398,14 +398,14 @@ int TSegment::RenderLoft( CVertNormTex* &Output, Math3D::vector3 const &Origin,
::glVertex3f( pt.x, pt.y, pt.z ); // pt nie mamy gdzie zapamiętać?
}
else {
Output->x = pt.x;
Output->y = pt.y;
Output->z = pt.z;
Output->nx = norm.x;
Output->ny = norm.y;
Output->nz = norm.z;
Output->u = (jmm1 * ShapePoints[ j ].z + m1 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale;
Output->v = tv1;
Output->position.x = pt.x;
Output->position.y = pt.y;
Output->position.z = pt.z;
Output->normal.x = norm.x;
Output->normal.y = norm.y;
Output->normal.z = norm.z;
Output->texture.s = (jmm1 * ShapePoints[ j ].z + m1 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale;
Output->texture.t = tv1;
++Output;
}
++vertexcount;
@@ -431,14 +431,14 @@ int TSegment::RenderLoft( CVertNormTex* &Output, Math3D::vector3 const &Origin,
::glVertex3f( pt.x, pt.y, pt.z );
}
else {
Output->x = pt.x;
Output->y = pt.y;
Output->z = pt.z;
Output->nx = norm.x;
Output->ny = norm.y;
Output->nz = norm.z;
Output->u = (jmm2 * ShapePoints[ j ].z + m2 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale;
Output->v = tv2;
Output->position.x = pt.x;
Output->position.y = pt.y;
Output->position.z = pt.z;
Output->normal.x = norm.x;
Output->normal.y = norm.y;
Output->normal.z = norm.z;
Output->texture.s = (jmm2 * ShapePoints[ j ].z + m2 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale;
Output->texture.t = tv2;
++Output;
}
++vertexcount;
@@ -468,14 +468,14 @@ int TSegment::RenderLoft( CVertNormTex* &Output, Math3D::vector3 const &Origin,
::glVertex3f( pt.x, pt.y, pt.z ); // punkt na początku odcinka
}
else {
Output->x = pt.x;
Output->y = pt.y;
Output->z = pt.z;
Output->nx = norm.x;
Output->ny = norm.y;
Output->nz = norm.z;
Output->u = ShapePoints[ j ].z / Texturescale;
Output->v = tv1;
Output->position.x = pt.x;
Output->position.y = pt.y;
Output->position.z = pt.z;
Output->normal.x = norm.x;
Output->normal.y = norm.y;
Output->normal.z = norm.z;
Output->texture.s = ShapePoints[ j ].z / Texturescale;
Output->texture.t = tv1;
++Output;
}
++vertexcount;
@@ -492,14 +492,14 @@ int TSegment::RenderLoft( CVertNormTex* &Output, Math3D::vector3 const &Origin,
::glVertex3f( pt.x, pt.y, pt.z ); // punkt na końcu odcinka
}
else {
Output->x = pt.x;
Output->y = pt.y;
Output->z = pt.z;
Output->nx = norm.x;
Output->ny = norm.y;
Output->nz = norm.z;
Output->u = ShapePoints[ j ].z / Texturescale;
Output->v = tv2;
Output->position.x = pt.x;
Output->position.y = pt.y;
Output->position.z = pt.z;
Output->normal.x = norm.x;
Output->normal.y = norm.y;
Output->normal.z = norm.z;
Output->texture.s = ShapePoints[ j ].z / Texturescale;
Output->texture.t = tv2;
++Output;
}
++vertexcount;

View File

@@ -1091,7 +1091,7 @@ void TTrack::Compile(GLuint tex)
normal2 = normal1;
}
auto const origin = pMyNode->m_rootposition;
auto const origin { pMyNode->m_rootposition };
double roll1, roll2;
switch (iCategoryFlag & 15)
@@ -1866,7 +1866,7 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
normal2 = normal1;
}
auto const origin = pMyNode->m_rootposition;
auto const origin { pMyNode->m_rootposition };
double roll1, roll2;
switch (iCategoryFlag & 15)
@@ -2302,42 +2302,42 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
if (TextureID1) {
// jeśli podana tekstura nawierzchni
// we start with a vertex in the middle...
Vert->nx = 0.0;
Vert->ny = 1.0;
Vert->nz = 0.0;
Vert->u = 0.5;
Vert->v = 0.5;
Vert->x = oxz.x - origin.x;
Vert->y = oxz.y - origin.y;
Vert->z = oxz.z - origin.z;
Vert->normal.x = 0.0;
Vert->normal.y = 1.0;
Vert->normal.z = 0.0;
Vert->texture.s = 0.5;
Vert->texture.t = 0.5;
Vert->position.x = oxz.x - origin.x;
Vert->position.y = oxz.y - origin.y;
Vert->position.z = oxz.z - origin.z;
++Vert;
// ...and add one extra vertex to close the fan...
Vert->nx = 0.0;
Vert->ny = 1.0;
Vert->nz = 0.0;
Vert->normal.x = 0.0;
Vert->normal.y = 1.0;
Vert->normal.z = 0.0;
// mapowanie we współrzędnych scenerii
u = ( SwitchExtension->vPoints[ 0 ].x - oxz.x + origin.x ) / fTexLength;
v = ( SwitchExtension->vPoints[ 0 ].z - oxz.z + origin.z ) / ( fTexRatio1 * fTexLength );
Vert->u = cosa0 * u + sina0 * v + 0.5;
Vert->v = -sina0 * u + cosa0 * v + 0.5;
Vert->x = SwitchExtension->vPoints[ 0 ].x;
Vert->y = SwitchExtension->vPoints[ 0 ].y;
Vert->z = SwitchExtension->vPoints[ 0 ].z;
Vert->texture.s = cosa0 * u + sina0 * v + 0.5;
Vert->texture.t = -sina0 * u + cosa0 * v + 0.5;
Vert->position.x = SwitchExtension->vPoints[ 0 ].x;
Vert->position.y = SwitchExtension->vPoints[ 0 ].y;
Vert->position.z = SwitchExtension->vPoints[ 0 ].z;
++Vert;
// ...then draw the precalculated rest
for (i = SwitchExtension->iPoints + SwitchExtension->iRoads - 1; i >= 0; --i)
{
Vert->nx = 0.0;
Vert->ny = 1.0;
Vert->nz = 0.0;
Vert->normal.x = 0.0;
Vert->normal.y = 1.0;
Vert->normal.z = 0.0;
// mapowanie we współrzędnych scenerii
u = (SwitchExtension->vPoints[i].x - oxz.x + origin.x ) / fTexLength;
v = (SwitchExtension->vPoints[i].z - oxz.z + origin.z ) / (fTexRatio1 * fTexLength);
Vert->u = cosa0 * u + sina0 * v + 0.5;
Vert->v = -sina0 * u + cosa0 * v + 0.5;
Vert->x = SwitchExtension->vPoints[ i ].x;
Vert->y = SwitchExtension->vPoints[ i ].y;
Vert->z = SwitchExtension->vPoints[ i ].z;
Vert->texture.s = cosa0 * u + sina0 * v + 0.5;
Vert->texture.t = -sina0 * u + cosa0 * v + 0.5;
Vert->position.x = SwitchExtension->vPoints[ i ].x;
Vert->position.y = SwitchExtension->vPoints[ i ].y;
Vert->position.z = SwitchExtension->vPoints[ i ].z;
++Vert;
}
}
@@ -2894,7 +2894,7 @@ TTrack * TTrack::RaAnimate(GLuint const Vertexbuffer)
bladesbuffer.data() );
*/
auto bladevertices = bladesbuffer.data();
auto const origin = pMyNode->m_rootposition;
auto const origin { pMyNode->m_rootposition };
if( SwitchExtension->RightSwitch ) { // nowa wersja z SPKS, ale odwrotnie lewa/prawa
SwitchExtension->Segments[ 0 ]->RenderLoft( bladevertices, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 /*, true*/ );
SwitchExtension->Segments[ 1 ]->RenderLoft( bladevertices, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 /*, true*/ );

View File

@@ -91,7 +91,7 @@ sekcji z sąsiedniego przęsła).
*/
std::size_t
TTraction::create_geometry( geometrybank_handle const &Bank, Math3D::vector3 const &Origin ) {
TTraction::create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &Origin ) {
if( m_geometry != NULL ) {
return GfxRenderer.Vertices( m_geometry ).size() / 2;
@@ -117,13 +117,13 @@ TTraction::create_geometry( geometrybank_handle const &Bank, Math3D::vector3 con
vertices.emplace_back( startvertex );
vertices.emplace_back( endvertex );
// Nie wiem co 'Marcin
Math3D::vector3 pt1, pt2, pt3, pt4, v1, v2;
glm::dvec3 pt1, pt2, pt3, pt4, v1, v2;
v1 = pPoint4 - pPoint3;
v2 = pPoint2 - pPoint1;
float step = 0;
if( iNumSections > 0 )
step = 1.0f / (float)iNumSections;
float f = step;
double f = step;
float mid = 0.5;
float t;
// Przewod nosny 'Marcin
@@ -274,13 +274,13 @@ TTraction::create_geometry( geometrybank_handle const &Bank, Math3D::vector3 con
return elementcount;
}
int TTraction::TestPoint(Math3D::vector3 *Point)
int TTraction::TestPoint(glm::dvec3 const &Point)
{ // sprawdzanie, czy przęsła można połączyć
if (!hvNext[0])
if (pPoint1.Equal(Point))
if( glm::all( glm::epsilonEqual( Point, pPoint1, 0.025 ) ) )
return 0;
if (!hvNext[1])
if (pPoint2.Equal(Point))
if( glm::all( glm::epsilonEqual( Point, pPoint2, 0.025 ) ) )
return 1;
return -1;
};
@@ -358,7 +358,7 @@ void TTraction::ResistanceCalc(int d, double r, TTractionPowerSource *ps)
}
t->psPower[d] = ps; // skopiowanie wskaźnika zasilacza od danej strony
t->fResistance[d] = r; // wpisanie rezystancji w kierunku tego zasilacza
r += t->fResistivity * Length3(t->vParametric); // doliczenie oporu kolejnego odcinka
r += t->fResistivity * glm::dot(t->vParametric, t->vParametric ); // doliczenie oporu kolejnego odcinka
p = t; // zapamiętanie dotychczasowego
t = p->hvNext[d ^ 1]; // podążanie w tę samą stronę
d = p->iNext[d ^ 1];
@@ -368,7 +368,7 @@ void TTraction::ResistanceCalc(int d, double r, TTractionPowerSource *ps)
else
{ // podążanie w obu kierunkach, można by rekurencją, ale szkoda zasobów
r = 0.5 * fResistivity *
Length3(vParametric); // powiedzmy, że w zasilanym przęśle jest połowa
glm::dot(vParametric, vParametric ); // powiedzmy, że w zasilanym przęśle jest połowa
if (fResistance[0] == 0.0)
ResistanceCalc(0, r); // do tyłu (w stronę Point1)
if (fResistance[1] == 0.0)

View File

@@ -27,8 +27,8 @@ class TTraction
int iNext[ 2 ] { 0, 0 }; // do którego końca się łączy
int iLast { 1 }; //że niby ostatni drut // ustawiony bit 0, jeśli jest ostatnim drutem w sekcji; bit1 - przedostatni
public:
Math3D::vector3 pPoint1, pPoint2, pPoint3, pPoint4;
Math3D::vector3 vParametric; // współczynniki równania parametrycznego odcinka
glm::dvec3 pPoint1, pPoint2, pPoint3, pPoint4;
glm::dvec3 vParametric; // współczynniki równania parametrycznego odcinka
double fHeightDifference { 0.0 }; //,fMiddleHeight;
int iNumSections { 0 };
float NominalVoltage { 0.0f };
@@ -51,8 +51,8 @@ class TTraction
// creates geometry data in specified geometry bank. returns: number of created elements, or NULL
// NOTE: deleting nodes doesn't currently release geometry data owned by the node. TODO: implement erasing individual geometry chunks and banks
std::size_t create_geometry( geometrybank_handle const &Bank, Math3D::vector3 const &Origin );
int TestPoint(Math3D::vector3 *Point);
std::size_t create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &Origin );
int TestPoint(glm::dvec3 const &Point);
void Connect(int my, TTraction *with, int to);
void Init();
bool WhereIs();

View File

@@ -14,7 +14,7 @@ http://mozilla.org/MPL/2.0/.
#include "sn_utils.h"
#include "globals.h"
//---------------------------------------------------------------------------
/*
void CVertNormTex::deserialize(std::istream &s)
{
x = sn_utils::ld_float32(s);
@@ -42,7 +42,7 @@ void CVertNormTex::serialize(std::ostream &s)
sn_utils::ls_float32(s, u);
sn_utils::ls_float32(s, v);
}
*/
CMesh::CMesh()
{ // utworzenie pustego obiektu
#ifdef EU07_USE_OLD_VERTEXBUFFER
@@ -117,7 +117,7 @@ bool CMesh::StartVBO()
if (m_nVBOVertices)
{
glBindBuffer(GL_ARRAY_BUFFER_ARB, m_nVBOVertices);
glVertexPointer( 3, GL_FLOAT, sizeof(CVertNormTex), static_cast<char *>(nullptr) ); // pozycje
glVertexPointer( 3, GL_FLOAT, sizeof( CVertNormTex ), static_cast<char *>( nullptr ) ); // pozycje
glNormalPointer( GL_FLOAT, sizeof( CVertNormTex ), static_cast<char *>( nullptr ) + 12 ); // normalne
glTexCoordPointer( 2, GL_FLOAT, sizeof( CVertNormTex ), static_cast<char *>( nullptr ) + 24 ); // wierzchołki
return true; // można rysować z VBO

3
VBO.h
View File

@@ -14,6 +14,7 @@ http://mozilla.org/MPL/2.0/.
#define EU07_USE_OLD_VERTEXBUFFER
//---------------------------------------------------------------------------
/*
class CVertNormTex
{
public:
@@ -29,6 +30,8 @@ class CVertNormTex
void deserialize(std::istream&);
void serialize(std::ostream&);
};
*/
typedef basic_vertex CVertNormTex;
class CMesh
{ // wsparcie dla VBO

View File

@@ -72,6 +72,9 @@ class vector3
y = b;
z = c;
}
vector3( glm::dvec3 const &Vector ) :
x( Vector.x ), y( Vector.y ), z( Vector.z )
{}
// The int parameter is the number of elements to copy from initArray (3 or 4)
// explicit vector3(scalar_t* initArray, int arraySize = 3)

View File

@@ -367,9 +367,9 @@ opengl_renderer::Render( TGround *Ground ) {
for( int column = originx; column <= originx + segmentcount; ++column ) {
for( int row = originz; row <= originz + segmentcount; ++row ) {
auto *rectangle = &Ground->Rects[ column ][ row ];
if( m_camera.visible( rectangle->m_area ) ) {
Render( rectangle );
auto *cell = &Ground->Rects[ column ][ row ];
if( m_camera.visible( cell->m_area ) ) {
Render( cell );
}
}
}
@@ -387,8 +387,8 @@ opengl_renderer::Render( TGround *Ground ) {
int r = Ground->GetRowFromZ( Global::pCameraPosition.z );
TSubRect *tmp;
int i, j, k;
for( j = r - n; j <= r + n; j++ ) {
for( i = c - n; i <= c + n; i++ ) {
for( j = r - n; j <= r + n; ++j ) {
for( i = c - n; i <= c + n; ++i ) {
if( ( tmp = Ground->FastGetSubRect( i, j ) ) != nullptr ) {
// oznaczanie aktywnych sektorów
tmp->LoadNodes();
@@ -441,12 +441,29 @@ opengl_renderer::Render( TGround *Ground ) {
}
} while( ( i < 0 ) || ( j < 0 ) ); // są 4 przypadki, oprócz i=j=0
}
/*
// dodać renderowanie terenu z E3D - jedno VBO jest używane dla całego modelu, chyba że jest ich więcej
if( Global::bUseVBO ) {
if( Global::pTerrainCompact ) {
if( ( Global::pTerrainCompact != nullptr )
&& ( Global::pTerrainCompact->pModel != nullptr ) ) {
#ifdef EU07_USE_OLD_RENDERCODE
Global::pTerrainCompact->TerrainRenderVBO( TGroundRect::iFrameNumber );
#endif
// TODO: remap geometry of terrain cells to allow camera-centric rendering
::glPushMatrix();
::glTranslated( -Global::pCameraPosition.x, -Global::pCameraPosition.y, -Global::pCameraPosition.z );
TSubModel *submodel = Global::pTerrainCompact->pModel->Root;
while( submodel != nullptr ) {
if( submodel->iVisible == TGroundRect::iFrameNumber ) {
// tylko jeśli ma być widoczny w danej ramce (problem dla 0==false)
Render( submodel ); // sub kolejne (Next) się nie wyrenderują
}
submodel = submodel->NextGet();
}
::glPopMatrix();
}
}
*/
// renderowanie nieprzezroczystych
for( i = 0; i < Ground->iRendered; ++i ) {
Render( Ground->pRendered[ i ] );
@@ -456,43 +473,42 @@ opengl_renderer::Render( TGround *Ground ) {
}
// TODO: unify ground render code, until then old version is in place
#define EU07_USE_OLD_RENDERCODE
bool
opengl_renderer::Render( TGroundRect *Groundcell ) {
::glPushMatrix();
auto const &cellorigin = Groundcell->m_area.center;
// TODO: unify all math objects
auto const originoffset = Math3D::vector3( cellorigin.x, cellorigin.y, cellorigin.z ) - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
bool result{ false }; // will be true if we do any rendering
bool result { false }; // will be true if we do any rendering
// TODO: unify render paths
if( Global::bUseVBO ) {
if ( Groundcell->iLastDisplay != Groundcell->iFrameNumber)
{ // tylko jezeli dany kwadrat nie był jeszcze renderowany
if ( Groundcell->iLastDisplay != Groundcell->iFrameNumber) {
// tylko jezeli dany kwadrat nie był jeszcze renderowany
Groundcell->LoadNodes(); // ewentualne tworzenie siatek
if ( Groundcell->nRenderRect && Groundcell->StartVBO())
{
for (TGroundNode *node = Groundcell->nRenderRect; node; node = node->nNext3) // następny tej grupy
#ifdef EU07_USE_OLD_RENDERCODE
node->RaRenderVBO(); // nieprzezroczyste trójkąty kwadratu kilometrowego
#else
Render( node ); // nieprzezroczyste trójkąty kwadratu kilometrowego
#endif
if( ( Groundcell->nRenderRect != nullptr )
&& ( true == Groundcell->StartVBO() ) ) {
// nieprzezroczyste trójkąty kwadratu kilometrowego
for( TGroundNode *node = Groundcell->nRenderRect; node; node = node->nNext3 ) {
Render( node );
}
Groundcell->EndVBO();
Groundcell->iLastDisplay = Groundcell->iFrameNumber;
result = true;
}
if ( Groundcell->nTerrain)
Groundcell->nTerrain->smTerrain->iVisible = Groundcell->iFrameNumber; // ma się wyświetlić w tej ramce
if( Groundcell->nTerrain ) {
Render( Groundcell->nTerrain );
}
Groundcell->iLastDisplay = Groundcell->iFrameNumber; // drugi raz nie potrzeba
result = true;
}
::glPopMatrix();
}
else {
#ifdef EU07_USE_OLD_RENDERCODE
// display list render path
::glPushMatrix();
auto const &cellorigin = Groundcell->m_area.center;
// TODO: unify all math objects
auto const originoffset = Math3D::vector3( cellorigin.x, cellorigin.y, cellorigin.z ) - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
if (Groundcell->iLastDisplay != Groundcell->iFrameNumber)
{ // tylko jezeli dany kwadrat nie był jeszcze renderowany
// for (TGroundNode* node=pRender;node;node=node->pNext3)
@@ -505,7 +521,7 @@ opengl_renderer::Render( TGroundRect *Groundcell ) {
Groundcell->nRender->DisplayListID = glGenLists(1);
glNewList( Groundcell->nRender->DisplayListID, GL_COMPILE);
Groundcell->nRender->iVersion = Global::iReCompile; // aktualna wersja siatek
auto const origin = Math3D::vector3( Groundcell->m_area.center.x, Groundcell->m_area.center.y, Groundcell->m_area.center.z );
auto const origin = glm::dvec3( Groundcell->m_area.center );
for (TGroundNode *node = Groundcell->nRender; node; node = node->nNext3) // następny tej grupy
node->Compile(origin, true);
glEndList();
@@ -515,32 +531,18 @@ opengl_renderer::Render( TGroundRect *Groundcell ) {
// submodels geometry is world-centric, so at least for the time being we need to pop the stack early
::glPopMatrix();
if( Groundcell->nRootMesh ) {
Render( Groundcell->nRootMesh );
}
if( Groundcell->nTerrain ) { Render( Groundcell->nTerrain ); }
Groundcell->iLastDisplay = Groundcell->iFrameNumber; // drugi raz nie potrzeba
result = true;
}
else {
::glPopMatrix();
}
#else
if( iLastDisplay != iFrameNumber ) { // tylko jezeli dany kwadrat nie był jeszcze renderowany
LoadNodes(); // ewentualne tworzenie siatek
if( nRenderRect ) {
for( TGroundNode *node = nRenderRect; node; node = node->nNext3 ) // następny tej grupy
Render( node ); // nieprzezroczyste trójkąty kwadratu kilometrowego
}
if( nRootMesh )
Render( nRootMesh );
iLastDisplay = iFrameNumber;
}
#endif
}
return result;
}
#undef EU07_USE_OLD_RENDERCODE
bool
opengl_renderer::Render( TSubRect *Groundsubcell ) {
@@ -665,11 +667,13 @@ opengl_renderer::Render( TGroundNode *Node ) {
if( Node->iNumPts ) {
// setup
// w zaleznosci od koloru swiatla
::glColor4ub(
static_cast<GLubyte>( std::floor( Node->Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ] ) ),
static_cast<GLubyte>( std::floor( Node->Diffuse[ 1 ] * Global::DayLight.ambient[ 1 ] ) ),
static_cast<GLubyte>( std::floor( Node->Diffuse[ 2 ] * Global::DayLight.ambient[ 2 ] ) ),
static_cast<GLubyte>( std::min( 255.0, 255000 * Node->fLineThickness / ( distancesquared + 1.0 ) ) ) );
::glColor4fv(
glm::value_ptr(
glm::vec4(
Node->Diffuse * glm::make_vec3( Global::DayLight.ambient ),
std::min(
1.0,
1000.0 * Node->fLineThickness / ( distancesquared + 1.0 ) ) ) ) );
GfxRenderer.Bind( 0 );
@@ -700,10 +704,7 @@ opengl_renderer::Render( TGroundNode *Node ) {
return false;
}
// setup
::glColor3ub(
static_cast<GLubyte>( Node->Diffuse[ 0 ] ),
static_cast<GLubyte>( Node->Diffuse[ 1 ] ),
static_cast<GLubyte>( Node->Diffuse[ 2 ] ) );
::glColor3fv( glm::value_ptr( Node->Diffuse ) );
Bind( Node->TextureID );
@@ -874,11 +875,11 @@ opengl_renderer::Render( TSubModel *Submodel ) {
// również 0
Bind( Submodel->TextureID );
}
::glColor3fv( Submodel->f4Diffuse ); // McZapkie-240702: zamiast ub
::glColor3fv( glm::value_ptr(Submodel->f4Diffuse) ); // McZapkie-240702: zamiast ub
// ...luminance
if( Global::fLuminance < Submodel->fLight ) {
// zeby swiecilo na kolorowo
::glMaterialfv( GL_FRONT, GL_EMISSION, Submodel->f4Diffuse );
::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr(Submodel->f4Diffuse) );
}
// main draw call
@@ -1184,11 +1185,13 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// w zaleznosci od koloru swiatla
::glColor4ub(
static_cast<GLubyte>( std::floor( Node->Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ] ) ),
static_cast<GLubyte>( std::floor( Node->Diffuse[ 1 ] * Global::DayLight.ambient[ 1 ] ) ),
static_cast<GLubyte>( std::floor( Node->Diffuse[ 2 ] * Global::DayLight.ambient[ 2 ] ) ),
static_cast<GLubyte>( std::min( 255.0, 255000 * Node->fLineThickness / ( distancesquared + 1.0 ) ) ) );
::glColor4fv(
glm::value_ptr(
glm::vec4(
Node->Diffuse * glm::make_vec3( Global::DayLight.ambient ),
std::min(
1.0,
1000.0 * Node->fLineThickness / ( distancesquared + 1.0 ) ) ) ) );
GfxRenderer.Bind( 0 );
@@ -1212,10 +1215,7 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
::glColor3ub(
static_cast<GLubyte>( Node->Diffuse[ 0 ] ),
static_cast<GLubyte>( Node->Diffuse[ 1 ] ),
static_cast<GLubyte>( Node->Diffuse[ 2 ] ) );
::glColor3fv( glm::value_ptr( Node->Diffuse ) );
Bind( Node->TextureID );
@@ -1392,11 +1392,11 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
// również 0
Bind( Submodel->TextureID );
}
::glColor3fv( Submodel->f4Diffuse ); // McZapkie-240702: zamiast ub
::glColor3fv( glm::value_ptr(Submodel->f4Diffuse) ); // McZapkie-240702: zamiast ub
// ...luminance
if( Global::fLuminance < Submodel->fLight ) {
// zeby swiecilo na kolorowo
::glMaterialfv( GL_FRONT, GL_EMISSION, Submodel->f4Diffuse );
::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr(Submodel->f4Diffuse) );
}
// main draw call

View File

@@ -85,5 +85,8 @@
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/epsilon.hpp>
#include <glm/gtx/rotate_vector.hpp>
#include <glm/gtx/norm.hpp>
#include "openglmatrixstack.h"

View File

@@ -59,9 +59,16 @@ clamp_circular( Type_ Value, Type_ const Range = static_cast<Type_>(360) ) {
template <typename Type_>
Type_
interpolate( Type_ const First, Type_ const Second, float const Factor ) {
interpolate( Type_ const &First, Type_ const &Second, float const Factor ) {
return ( First * ( 1.0f - Factor ) ) + ( Second * Factor );
}
template <typename Type_>
Type_
interpolate( Type_ const &First, Type_ const &Second, double const Factor ) {
return ( First * ( 1.0 - Factor ) ) + ( Second * Factor );
}
//---------------------------------------------------------------------------