mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-19 06:29:18 +02:00
early implementation of geometry bank, partial replacement of math classes with glm
This commit is contained in:
@@ -263,6 +263,13 @@ inline float3 operator*(const float4x4 &m, const float3 &v)
|
||||
v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2] + m[3][2]);
|
||||
}
|
||||
|
||||
inline glm::vec3 operator*( const float4x4 &m, const glm::vec3 &v ) { // mnożenie wektora przez macierz
|
||||
return glm::vec3(
|
||||
v.x * m[ 0 ][ 0 ] + v.y * m[ 1 ][ 0 ] + v.z * m[ 2 ][ 0 ] + m[ 3 ][ 0 ],
|
||||
v.x * m[ 0 ][ 1 ] + v.y * m[ 1 ][ 1 ] + v.z * m[ 2 ][ 1 ] + m[ 3 ][ 1 ],
|
||||
v.x * m[ 0 ][ 2 ] + v.y * m[ 1 ][ 2 ] + v.z * m[ 2 ][ 2 ] + m[ 3 ][ 2 ] );
|
||||
}
|
||||
|
||||
inline float4x4 &float4x4::Rotation(double angle, float3 axis)
|
||||
{
|
||||
double c = cos(angle);
|
||||
|
||||
18
Ground.cpp
18
Ground.cpp
@@ -4348,7 +4348,7 @@ void TGround::TerrainWrite()
|
||||
// int ver=0; //całkowita ilość wierzchołków
|
||||
int i, j, k; // indeksy w pętli
|
||||
TGroundNode *Current;
|
||||
float8 *ver; // trójkąty
|
||||
basic_vertex *ver; // trójkąty
|
||||
TSubModel::iInstance = 0; // pozycja w tabeli wierzchołków liczona narastająco
|
||||
for (i = 0; i < iNumRects; ++i) // pętla po wszystkich kwadratach kilometrowych
|
||||
for (j = 0; j < iNumRects; ++j)
|
||||
@@ -4395,14 +4395,14 @@ void TGround::TerrainWrite()
|
||||
Current->iVboPtr = -1; // bo to było tymczasowo używane
|
||||
for (k = 0; k < Current->iNumVerts; ++k)
|
||||
{ // przepisanie współrzędnych
|
||||
ver[k].Point.x = Current->Vertices[k].Point.x;
|
||||
ver[k].Point.y = Current->Vertices[k].Point.y;
|
||||
ver[k].Point.z = Current->Vertices[k].Point.z;
|
||||
ver[k].Normal.x = Current->Vertices[k].Normal.x;
|
||||
ver[k].Normal.y = Current->Vertices[k].Normal.y;
|
||||
ver[k].Normal.z = Current->Vertices[k].Normal.z;
|
||||
ver[k].tu = Current->Vertices[k].tu;
|
||||
ver[k].tv = Current->Vertices[k].tv;
|
||||
ver[k].position.x = Current->Vertices[k].Point.x;
|
||||
ver[k].position.y = Current->Vertices[k].Point.y;
|
||||
ver[k].position.z = Current->Vertices[k].Point.z;
|
||||
ver[k].normal.x = Current->Vertices[k].Normal.x;
|
||||
ver[k].normal.y = Current->Vertices[k].Normal.y;
|
||||
ver[k].normal.z = Current->Vertices[k].Normal.z;
|
||||
ver[k].texture.s = Current->Vertices[k].tu;
|
||||
ver[k].texture.t = Current->Vertices[k].tv;
|
||||
}
|
||||
break;
|
||||
case GL_TRIANGLE_STRIP: // na razie nie, bo trzeba przerabiać na pojedyncze
|
||||
|
||||
288
Model3d.cpp
288
Model3d.cpp
@@ -113,11 +113,6 @@ TSubModel::~TSubModel()
|
||||
delete fMatrix; // własny transform trzeba usunąć (zawsze jeden)
|
||||
delete[] Vertices;
|
||||
}
|
||||
/*
|
||||
else
|
||||
{//wczytano z pliku binarnego (nie jest właścicielem tablic)
|
||||
}
|
||||
*/
|
||||
delete[] smLetter; // używany tylko roboczo dla TP_TEXT, do przyspieszenia
|
||||
// wyświetlania
|
||||
};
|
||||
@@ -141,23 +136,23 @@ void TSubModel::NameSet(const char *n)
|
||||
// int TSubModel::SeekFaceNormal(DWORD *Masks, int f,DWORD dwMask,vector3
|
||||
// *pt,GLVERTEX
|
||||
// *Vertices)
|
||||
int TSubModel::SeekFaceNormal(unsigned int *Masks, int f, unsigned int dwMask, float3 *pt,
|
||||
float8 *Vertices)
|
||||
int TSubModel::SeekFaceNormal(unsigned int *Masks, int f, unsigned int dwMask, glm::vec3 *pt,
|
||||
basic_vertex *Vertices)
|
||||
{ // szukanie punktu stycznego
|
||||
// do (pt), zwraca numer
|
||||
// wierzchołka, a nie trójkąta
|
||||
int iNumFaces = iNumVerts / 3; // bo maska powierzchni jest jedna na trójkąt
|
||||
// GLVERTEX *p; //roboczy wskaźnik
|
||||
float8 *p; // roboczy wskaźnik
|
||||
basic_vertex *p; // roboczy wskaźnik
|
||||
for (int i = f; i < iNumFaces; ++i) // pętla po trójkątach, od trójkąta (f)
|
||||
if (Masks[i] & dwMask) // jeśli wspólna maska powierzchni
|
||||
{
|
||||
p = Vertices + 3 * i;
|
||||
if (p->Point == *pt)
|
||||
if (p->position == *pt)
|
||||
return 3 * i;
|
||||
if ((++p)->Point == *pt)
|
||||
if ((++p)->position == *pt)
|
||||
return 3 * i + 1;
|
||||
if ((++p)->Point == *pt)
|
||||
if ((++p)->position == *pt)
|
||||
return 3 * i + 2;
|
||||
}
|
||||
return -1; // nie znaleziono stycznego wierzchołka
|
||||
@@ -446,7 +441,7 @@ int TSubModel::Load(cParser &parser, TModel3d *Model, int Pos, bool dynamic)
|
||||
// Vertices=new GLVERTEX[iNumVerts];
|
||||
if (iNumVerts)
|
||||
{
|
||||
Vertices = new float8[iNumVerts];
|
||||
Vertices = new basic_vertex[iNumVerts];
|
||||
iNumFaces = iNumVerts / 3;
|
||||
sg = new unsigned int[iNumFaces]; // maski powierzchni: 0 oznacza brak
|
||||
// użredniania wektorów normalnych
|
||||
@@ -467,21 +462,28 @@ int TSubModel::Load(cParser &parser, TModel3d *Model, int Pos, bool dynamic)
|
||||
// wektorów normalnych
|
||||
}
|
||||
parser.getTokens(3, false);
|
||||
parser >> Vertices[i].Point.x >> Vertices[i].Point.y >> Vertices[i].Point.z;
|
||||
parser
|
||||
>> Vertices[i].position.x
|
||||
>> Vertices[i].position.y
|
||||
>> Vertices[i].position.z;
|
||||
if (maska == -1)
|
||||
{ // jeśli wektory normalne podane jawnie
|
||||
parser.getTokens(3, false);
|
||||
parser >> Vertices[i].Normal.x >> Vertices[i].Normal.y >>
|
||||
Vertices[i].Normal.z;
|
||||
parser
|
||||
>> Vertices[i].normal.x
|
||||
>> Vertices[i].normal.y
|
||||
>> Vertices[i].normal.z;
|
||||
wsp[i] = i; // wektory normalne "są już policzone"
|
||||
}
|
||||
parser.getTokens(2, false);
|
||||
parser >> Vertices[i].tu >> Vertices[i].tv;
|
||||
parser
|
||||
>> Vertices[i].texture.s
|
||||
>> Vertices[i].texture.t;
|
||||
if (i % 3 == 2) // jeżeli wczytano 3 punkty
|
||||
{
|
||||
if (Vertices[i].Point == Vertices[i - 1].Point ||
|
||||
Vertices[i - 1].Point == Vertices[i - 2].Point ||
|
||||
Vertices[i - 2].Point == Vertices[i].Point)
|
||||
if (Vertices[i].position == Vertices[i - 1].position
|
||||
|| Vertices[i - 1].position == Vertices[i - 2].position
|
||||
|| Vertices[i - 2].position == Vertices[i].position)
|
||||
{ // jeżeli punkty się nakładają na siebie
|
||||
--iNumFaces; // o jeden trójkąt mniej
|
||||
iNumVerts -= 3; // czyli o 3 wierzchołki
|
||||
@@ -491,10 +493,9 @@ int TSubModel::Load(cParser &parser, TModel3d *Model, int Pos, bool dynamic)
|
||||
}
|
||||
if (i > 0) // jeśli pierwszy trójkąt będzie zdegenerowany, to
|
||||
// zostanie usunięty i nie ma co sprawdzać
|
||||
if (((Vertices[i].Point - Vertices[i - 1].Point).Length() > 1000.0) ||
|
||||
((Vertices[i - 1].Point - Vertices[i - 2].Point).Length() >
|
||||
1000.0) ||
|
||||
((Vertices[i - 2].Point - Vertices[i].Point).Length() > 1000.0))
|
||||
if ((glm::length(Vertices[i].position - Vertices[i - 1].position) > 1000.0)
|
||||
|| (glm::length(Vertices[i - 1].position - Vertices[i - 2].position) > 1000.0)
|
||||
|| (glm::length(Vertices[i - 2].position - Vertices[i].position) > 1000.0))
|
||||
{ // jeżeli są dalej niż 2km od siebie //Ra 15-01:
|
||||
// obiekt wstawiany nie powinien być większy niż
|
||||
// 300m (trójkąty terenu w E3D mogą mieć 1.5km)
|
||||
@@ -507,26 +508,27 @@ int TSubModel::Load(cParser &parser, TModel3d *Model, int Pos, bool dynamic)
|
||||
}
|
||||
}
|
||||
int i; // indeks dla trójkątów
|
||||
float3 *n = new float3[iNumFaces]; // tablica wektorów normalnych dla trójkątów
|
||||
for (i = 0; i < iNumFaces; i++) // pętla po trójkątach - będzie
|
||||
glm::vec3 *n = new glm::vec3[iNumFaces]; // tablica wektorów normalnych dla trójkątów
|
||||
for (i = 0; i < iNumFaces; ++i) // pętla po trójkątach - będzie
|
||||
// szybciej, jak wstępnie przeliczymy
|
||||
// normalne trójkątów
|
||||
n[i] = SafeNormalize(
|
||||
CrossProduct(Vertices[i * 3].Point - Vertices[i * 3 + 1].Point,
|
||||
Vertices[i * 3].Point - Vertices[i * 3 + 2].Point));
|
||||
n[i] = glm::normalize(
|
||||
glm::cross(
|
||||
Vertices[i * 3].position - Vertices[i * 3 + 1].position,
|
||||
Vertices[i * 3].position - Vertices[i * 3 + 2].position));
|
||||
int v; // indeks dla wierzchołków
|
||||
int f; // numer trójkąta stycznego
|
||||
float3 norm; // roboczy wektor normalny
|
||||
for (v = 0; v < iNumVerts; v++)
|
||||
glm::vec3 norm; // roboczy wektor normalny
|
||||
for (v = 0; v < iNumVerts; ++v)
|
||||
{ // pętla po wierzchołkach trójkątów
|
||||
if (wsp[v] >= 0) // jeśli już był liczony wektor normalny z użyciem
|
||||
// tego wierzchołka
|
||||
Vertices[v].Normal =
|
||||
Vertices[wsp[v]].Normal; // to wystarczy skopiować policzony wcześniej
|
||||
Vertices[v].normal =
|
||||
Vertices[wsp[v]].normal; // to wystarczy skopiować policzony wcześniej
|
||||
else
|
||||
{ // inaczej musimy dopiero policzyć
|
||||
i = v / 3; // numer trójkąta
|
||||
norm = float3(0, 0, 0); // liczenie zaczynamy od zera
|
||||
norm = glm::vec3(); // liczenie zaczynamy od zera
|
||||
f = v; // zaczynamy dodawanie wektorów normalnych od własnego
|
||||
while (f >= 0)
|
||||
{ // sumowanie z wektorem normalnym sąsiada (włącznie
|
||||
@@ -534,13 +536,13 @@ int TSubModel::Load(cParser &parser, TModel3d *Model, int Pos, bool dynamic)
|
||||
wsp[f] = v; // informacja, że w tym wierzchołku jest już policzony
|
||||
// wektor normalny
|
||||
norm += n[f / 3];
|
||||
f = SeekFaceNormal(sg, f / 3 + 1, sg[i], &Vertices[v].Point,
|
||||
f = SeekFaceNormal(sg, f / 3 + 1, sg[i], &Vertices[v].position,
|
||||
Vertices); // i szukanie od kolejnego trójkąta
|
||||
}
|
||||
// Ra 15-01: należało by jeszcze uwzględnić skalowanie wprowadzane
|
||||
// przez transformy, aby normalne po przeskalowaniu były jednostkowe
|
||||
Vertices[v].Normal =
|
||||
SafeNormalize(norm); // przepisanie do wierzchołka trójkąta
|
||||
Vertices[v].normal =
|
||||
glm::normalize(norm); // przepisanie do wierzchołka trójkąta
|
||||
}
|
||||
}
|
||||
delete[] wsp;
|
||||
@@ -561,21 +563,24 @@ int TSubModel::Load(cParser &parser, TModel3d *Model, int Pos, bool dynamic)
|
||||
parser.getTokens(2, false);
|
||||
parser >> discard >> iNumVerts;
|
||||
// Vertices=new GLVERTEX[iNumVerts];
|
||||
Vertices = new float8[iNumVerts];
|
||||
Vertices = new basic_vertex[iNumVerts];
|
||||
int i, j;
|
||||
for (i = 0; i < iNumVerts; i++)
|
||||
for (i = 0; i < iNumVerts; ++i)
|
||||
{
|
||||
if (i % 3 == 0)
|
||||
{
|
||||
parser.ignoreToken(); // maska powierzchni trójkąta
|
||||
}
|
||||
parser.getTokens(5, false);
|
||||
parser >> Vertices[i].Point.x >> Vertices[i].Point.y >> Vertices[i].Point.z >>
|
||||
j // zakodowany kolor
|
||||
parser
|
||||
>> Vertices[i].position.x
|
||||
>> Vertices[i].position.y
|
||||
>> Vertices[i].position.z
|
||||
>> j // zakodowany kolor
|
||||
>> discard;
|
||||
Vertices[i].Normal.x = ((j) & 0xFF) / 255.0; // R
|
||||
Vertices[i].Normal.y = ((j >> 8) & 0xFF) / 255.0; // G
|
||||
Vertices[i].Normal.z = ((j >> 16) & 0xFF) / 255.0; // B
|
||||
Vertices[i].normal.x = ((j) & 0xFF) / 255.0; // R
|
||||
Vertices[i].normal.y = ((j >> 8) & 0xFF) / 255.0; // G
|
||||
Vertices[i].normal.z = ((j >> 16) & 0xFF) / 255.0; // B
|
||||
}
|
||||
}
|
||||
// Visible=true; //się potem wyłączy w razie potrzeby
|
||||
@@ -605,11 +610,9 @@ int TSubModel::TriangleAdd(TModel3d *m, texture_manager::size_type tex, int tri)
|
||||
s = new TSubModel();
|
||||
m->AddTo(this, s);
|
||||
}
|
||||
// s->asTexture=AnsiString(TTexturesManager::GetName(tex).c_str());
|
||||
s->TextureNameSet(GfxRenderer.Texture(tex).name.c_str());
|
||||
s->TextureID = tex;
|
||||
s->eType = GL_TRIANGLES;
|
||||
// iAnimOwner=0; //roboczy wskaźnik na wierzchołek
|
||||
}
|
||||
if (s->iNumVerts < 0)
|
||||
s->iNumVerts = tri; // bo na początku jest -1, czyli że nie wiadomo
|
||||
@@ -618,7 +621,7 @@ int TSubModel::TriangleAdd(TModel3d *m, texture_manager::size_type tex, int tri)
|
||||
return s->iNumVerts - tri; // zwraca pozycję tych trójkątów w submodelu
|
||||
};
|
||||
|
||||
float8 *TSubModel::TrianglePtr(int tex, int pos, int *la, int *ld, int *ls)
|
||||
basic_vertex *TSubModel::TrianglePtr(int tex, int pos, int *la, int *ld, int *ls)
|
||||
{ // zwraca wskaźnik do wypełnienia tabeli wierzchołków, używane
|
||||
// przy tworzeniu E3D terenu
|
||||
TSubModel *s = this;
|
||||
@@ -633,9 +636,7 @@ float8 *TSubModel::TrianglePtr(int tex, int pos, int *la, int *ld, int *ls)
|
||||
return NULL; // coś nie tak poszło
|
||||
if (!s->Vertices)
|
||||
{ // utworznie tabeli trójkątów
|
||||
s->Vertices = new float8[s->iNumVerts];
|
||||
// iVboPtr=pos; //pozycja submodelu w tabeli wierzchołków
|
||||
// pos+=iNumVerts; //rezerwacja miejsca w tabeli
|
||||
s->Vertices = new basic_vertex[s->iNumVerts];
|
||||
s->iVboPtr = iInstance; // pozycja submodelu w tabeli wierzchołków
|
||||
iInstance += s->iNumVerts; // pozycja dla następnego
|
||||
}
|
||||
@@ -648,7 +649,6 @@ void TSubModel::DisplayLists()
|
||||
// każdego submodelu
|
||||
if (Global::bUseVBO)
|
||||
return; // Ra: przy VBO to się nie przyda
|
||||
// iFlags|=0x4000; //wyłączenie przeliczania wierzchołków, bo nie są zachowane
|
||||
if (eType < TP_ROTATOR)
|
||||
{
|
||||
if (iNumVerts > 0)
|
||||
@@ -670,9 +670,9 @@ void TSubModel::DisplayLists()
|
||||
glTexCoord2f(Vertices[i].tu,Vertices[i].tv);
|
||||
glVertex3dv(&Vertices[i].Point.x);
|
||||
*/
|
||||
glNormal3fv(&Vertices[i].Normal.x);
|
||||
glTexCoord2f(Vertices[i].tu, Vertices[i].tv);
|
||||
glVertex3fv(&Vertices[i].Point.x);
|
||||
glNormal3fv(glm::value_ptr(Vertices[i].normal));
|
||||
glTexCoord2fv(glm::value_ptr(Vertices[i].texture));
|
||||
glVertex3fv(glm::value_ptr(Vertices[i].position));
|
||||
};
|
||||
glEnd();
|
||||
#endif
|
||||
@@ -693,10 +693,10 @@ void TSubModel::DisplayLists()
|
||||
uiDisplayList = glGenLists(1);
|
||||
glNewList(uiDisplayList, GL_COMPILE);
|
||||
glBegin(GL_POINTS);
|
||||
for (int i = 0; i < iNumVerts; i++)
|
||||
for (int i = 0; i < iNumVerts; ++i)
|
||||
{
|
||||
glColor3f(Vertices[i].Normal.x, Vertices[i].Normal.y, Vertices[i].Normal.z);
|
||||
glVertex3fv(&Vertices[i].Point.x);
|
||||
glColor3fv(glm::value_ptr(Vertices[i].normal));
|
||||
glVertex3fv(glm::value_ptr(Vertices[i].position));
|
||||
};
|
||||
glEnd();
|
||||
glEndList();
|
||||
@@ -736,13 +736,13 @@ void TSubModel::InitialRotate(bool doit)
|
||||
if (Vertices)
|
||||
{
|
||||
for (int i = 0; i < iNumVerts; ++i)
|
||||
Vertices[i].Point = (*mat) * Vertices[i].Point;
|
||||
Vertices[i].position = (*mat) * Vertices[i].position;
|
||||
(*mat)(3)[0] = (*mat)(3)[1] = (*mat)(3)[2] =
|
||||
0.0; // zerujemy przesunięcie przed obracaniem normalnych
|
||||
if (eType != TP_STARS) // gwiazdki mają kolory zamiast normalnych, to
|
||||
// ich wtedy nie ruszamy
|
||||
for (int i = 0; i < iNumVerts; ++i)
|
||||
Vertices[i].Normal = SafeNormalize((*mat) * Vertices[i].Normal);
|
||||
Vertices[i].normal = glm::normalize((*mat) * Vertices[i].normal);
|
||||
}
|
||||
mat->Identity(); // jedynkowanie transformu po przeliczeniu wierzchołków
|
||||
iFlags &= ~0x8000; // transform jedynkowy
|
||||
@@ -756,17 +756,17 @@ void TSubModel::InitialRotate(bool doit)
|
||||
if (Vertices)
|
||||
for (int i = 0; i < iNumVerts; ++i)
|
||||
{
|
||||
Vertices[i].Point.x = -Vertices[i].Point.x; // zmiana znaku X
|
||||
t = Vertices[i].Point.y; // zamiana Y i Z
|
||||
Vertices[i].Point.y = Vertices[i].Point.z;
|
||||
Vertices[i].Point.z = t;
|
||||
Vertices[i].position.x = -Vertices[i].position.x; // zmiana znaku X
|
||||
t = Vertices[i].position.y; // zamiana Y i Z
|
||||
Vertices[i].position.y = Vertices[i].position.z;
|
||||
Vertices[i].position.z = t;
|
||||
// wektory normalne również trzeba przekształcić, bo się źle oświetlają
|
||||
if( eType != TP_STARS ) {
|
||||
// gwiazdki mają kolory zamiast normalnych, to // ich wtedy nie ruszamy
|
||||
Vertices[ i ].Normal.x = -Vertices[ i ].Normal.x; // zmiana znaku X
|
||||
t = Vertices[ i ].Normal.y; // zamiana Y i Z
|
||||
Vertices[ i ].Normal.y = Vertices[ i ].Normal.z;
|
||||
Vertices[ i ].Normal.z = t;
|
||||
Vertices[ i ].normal.x = -Vertices[ i ].normal.x; // zmiana znaku X
|
||||
t = Vertices[ i ].normal.y; // zamiana Y i Z
|
||||
Vertices[ i ].normal.y = Vertices[ i ].normal.z;
|
||||
Vertices[ i ].normal.z = t;
|
||||
}
|
||||
}
|
||||
if (Child)
|
||||
@@ -1045,14 +1045,14 @@ void TSubModel::RaArrayFill(CVertNormTex *Vert)
|
||||
if ((eType < TP_ROTATOR) || (eType == TP_STARS))
|
||||
for (int i = 0; i < iNumVerts; ++i)
|
||||
{
|
||||
Vert[iVboPtr + i].x = Vertices[i].Point.x;
|
||||
Vert[iVboPtr + i].y = Vertices[i].Point.y;
|
||||
Vert[iVboPtr + i].z = Vertices[i].Point.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].tu;
|
||||
Vert[iVboPtr + i].v = Vertices[i].tv;
|
||||
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;
|
||||
@@ -1114,6 +1114,7 @@ float TSubModel::MaxY(const float4x4 &m)
|
||||
return 0; // tylko dla trójkątów liczymy
|
||||
if (iNumVerts < 1)
|
||||
return 0;
|
||||
/*
|
||||
if (!Vertices)
|
||||
return 0;
|
||||
float y,
|
||||
@@ -1126,6 +1127,22 @@ float TSubModel::MaxY(const float4x4 &m)
|
||||
if (my < y)
|
||||
my = y;
|
||||
}
|
||||
*/
|
||||
float my =
|
||||
m[ 0 ][ 1 ] * Vertices[ 0 ].position.x
|
||||
+ m[ 1 ][ 1 ] * Vertices[ 0 ].position.y
|
||||
+ m[ 2 ][ 1 ] * Vertices[ 0 ].position.z
|
||||
+ m[ 3 ][ 1 ];
|
||||
float y;
|
||||
for( int i = 1; i < iNumVerts; ++i ) {
|
||||
y =
|
||||
m[ 0 ][ 1 ] * Vertices[ i ].position.x
|
||||
+ m[ 1 ][ 1 ] * Vertices[ i ].position.y
|
||||
+ m[ 2 ][ 1 ] * Vertices[ i ].position.z
|
||||
+ m[ 3 ][ 1 ];
|
||||
|
||||
if( my < y ) { my = y; }
|
||||
}
|
||||
return my;
|
||||
};
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -1495,28 +1512,7 @@ void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
|
||||
uint32_t size = sn_utils::ld_uint32(s) - 8;
|
||||
std::streampos end = s.tellg() + (std::streampos)size;
|
||||
|
||||
if (type == MAKE_ID4('V', 'N', 'T', '0'))
|
||||
{
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
if (m_pVNT != nullptr)
|
||||
#else
|
||||
if( false == m_pVNT.empty() )
|
||||
#endif
|
||||
throw std::runtime_error("e3d: duplicated VNT chunk");
|
||||
|
||||
size_t vt_cnt = size / 32;
|
||||
iNumVerts = (int)vt_cnt;
|
||||
m_nVertexCount = (int)vt_cnt;
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
assert( m_pVNT == nullptr );
|
||||
m_pVNT = new CVertNormTex[vt_cnt];
|
||||
#else
|
||||
m_pVNT.resize( vt_cnt );
|
||||
#endif
|
||||
for (size_t i = 0; i < vt_cnt; i++)
|
||||
m_pVNT[i].deserialize(s);
|
||||
}
|
||||
else if ((type & 0x00FFFFFF) == MAKE_ID4('S', 'U', 'B', 0))
|
||||
if ((type & 0x00FFFFFF) == MAKE_ID4('S', 'U', 'B', 0))
|
||||
{
|
||||
if (Root != nullptr)
|
||||
throw std::runtime_error("e3d: duplicated SUB chunk");
|
||||
@@ -1532,6 +1528,66 @@ void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
|
||||
Root[i].deserialize(s);
|
||||
}
|
||||
}
|
||||
else if (type == MAKE_ID4('V', 'N', 'T', '0'))
|
||||
{
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
if (m_pVNT != nullptr)
|
||||
#else
|
||||
if( false == m_pVNT.empty() )
|
||||
#endif
|
||||
throw std::runtime_error("e3d: duplicated VNT chunk");
|
||||
|
||||
/*
|
||||
size_t vt_cnt = size / 32;
|
||||
iNumVerts = (int)vt_cnt;
|
||||
m_nVertexCount = (int)vt_cnt;
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
assert( m_pVNT == nullptr );
|
||||
m_pVNT = new CVertNormTex[vt_cnt];
|
||||
#else
|
||||
m_pVNT.resize( vt_cnt );
|
||||
#endif
|
||||
for (size_t i = 0; i < vt_cnt; i++)
|
||||
m_pVNT[i].deserialize(s);
|
||||
*/
|
||||
|
||||
// we rely on the SUB chunk coming before the vertex data, and on the overall vertex count matching the size of data in the chunk
|
||||
// geometry associated with chunks isn't stored in the order the actual chunks are listed, so we need to sort that out first
|
||||
std::vector< std::pair<int, int> > submodeloffsets;
|
||||
submodeloffsets.reserve( iSubModelsCount );
|
||||
for( int idx = 0; idx < iSubModelsCount; ++idx ) {
|
||||
auto &submodel = Root[ idx ];
|
||||
if( submodel.iNumVerts <= 0 ) { continue; }
|
||||
submodeloffsets.emplace_back( submodel.tVboPtr, idx );
|
||||
}
|
||||
std::sort(
|
||||
submodeloffsets.begin(),
|
||||
submodeloffsets.end(),
|
||||
[]( std::pair<int, int> const &Left, std::pair<int, int> const &Right ) {
|
||||
return (Left.first) < (Right.first); } );
|
||||
// once sorted we can grab geometry for the chunks as they come
|
||||
for( auto const &submodeloffset : submodeloffsets ) {
|
||||
auto &submodel = Root[ submodeloffset.second ];
|
||||
vertex_array vertices; vertices.resize( submodel.iNumVerts );
|
||||
for( auto &vertex : vertices ) {
|
||||
vertex.deserialize( s );
|
||||
}
|
||||
// remap geometry type for custom type submodels
|
||||
int type;
|
||||
switch( submodel.eType ) {
|
||||
case TP_FREESPOTLIGHT:
|
||||
case TP_STARS: {
|
||||
type = GL_POINTS;
|
||||
break; }
|
||||
default: {
|
||||
type = submodel.eType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
submodel.m_chunk = m_geometry->create( vertices, type );
|
||||
}
|
||||
|
||||
}
|
||||
else if (type == MAKE_ID4('T', 'R', 'A', '0'))
|
||||
{
|
||||
if (tm != nullptr)
|
||||
@@ -1572,18 +1628,23 @@ void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
|
||||
|
||||
if (!Root)
|
||||
throw std::runtime_error("e3d: no submodels");
|
||||
|
||||
/*
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
if (!m_pVNT)
|
||||
#else
|
||||
if(m_pVNT.empty() )
|
||||
#endif
|
||||
throw std::runtime_error("e3d: no vertices");
|
||||
|
||||
for (size_t i = 0; (int)i < iSubModelsCount; i++)
|
||||
*/
|
||||
for (size_t i = 0; (int)i < iSubModelsCount; ++i)
|
||||
{
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
Root[i].BinInit(Root, tm, (float8*)m_pVNT, &Textures, &Names, dynamic);
|
||||
Root[i].BinInit(
|
||||
Root, tm,
|
||||
( Root[i].m_chunk ?
|
||||
&m_geometry->data(Root[i].m_chunk)[0] :
|
||||
nullptr ),
|
||||
&Textures, &Names, dynamic);
|
||||
#else
|
||||
Root[ i ].BinInit( Root, tm, (float8*)m_pVNT.data(), &Textures, &Names, dynamic );
|
||||
#endif
|
||||
@@ -1595,7 +1656,7 @@ void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
|
||||
}
|
||||
}
|
||||
|
||||
void TSubModel::BinInit(TSubModel *s, float4x4 *m, float8 *v,
|
||||
void TSubModel::BinInit(TSubModel *s, float4x4 *m, basic_vertex *v,
|
||||
std::vector<std::string> *t, std::vector<std::string> *n, bool dynamic)
|
||||
{ // ustawienie wskaźników w submodelu
|
||||
//m7todo: brzydko
|
||||
@@ -1659,9 +1720,7 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, float8 *v,
|
||||
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
|
||||
// renderowało na siłę
|
||||
Vertices = v;
|
||||
};
|
||||
|
||||
void TModel3d::LoadFromBinFile(std::string const &FileName, bool dynamic)
|
||||
@@ -1696,27 +1755,26 @@ void TModel3d::LoadFromTextFile(std::string const &FileName, bool dynamic)
|
||||
// parser.getToken(parent);
|
||||
parser.getTokens(1, false); // nazwa submodelu nadrzędnego bez zmieny na małe
|
||||
parser >> parent;
|
||||
if (parent == "")
|
||||
break;
|
||||
if( parent == "" ) {
|
||||
break;
|
||||
}
|
||||
SubModel = new TSubModel();
|
||||
iNumVerts += SubModel->Load(parser, this, iNumVerts, dynamic);
|
||||
SubModel->Parent = AddToNamed(
|
||||
parent.c_str(), SubModel); // będzie potrzebne do wyliczenia pozycji, np. pantografu
|
||||
// iSubModelsCount++;
|
||||
|
||||
// będzie potrzebne do wyliczenia pozycji, np. pantografu
|
||||
SubModel->Parent = AddToNamed(parent.c_str(), SubModel);
|
||||
|
||||
parser.getTokens();
|
||||
parser >> token;
|
||||
}
|
||||
// Ra: od wersji 334 przechylany jest cały model, a nie tylko pierwszy
|
||||
// submodel
|
||||
// ale bujanie kabiny nadal używa bananów :( od 393 przywrócone, ale z
|
||||
// dodatkowym warunkiem
|
||||
// Ra: od wersji 334 przechylany jest cały model, a nie tylko pierwszy submodel
|
||||
// ale bujanie kabiny nadal używa bananów :( od 393 przywrócone, ale z dodatkowym warunkiem
|
||||
if (Global::iConvertModels & 4)
|
||||
{ // automatyczne banany czasem psuły przechylanie kabin...
|
||||
if (dynamic && Root)
|
||||
{
|
||||
if (Root->NextGet()) // jeśli ma jakiekolwiek kolejne
|
||||
{ // dynamic musi mieć "banana", bo tylko pierwszy obiekt jest animowany,
|
||||
// a następne nie
|
||||
{ // dynamic musi mieć "banana", bo tylko pierwszy obiekt jest animowany, a następne nie
|
||||
SubModel = new TSubModel(); // utworzenie pustego
|
||||
SubModel->ChildAdd(Root);
|
||||
Root = SubModel;
|
||||
|
||||
152
Model3d.h
152
Model3d.h
@@ -19,82 +19,6 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
using namespace Math3D;
|
||||
|
||||
struct GLVERTEX
|
||||
{
|
||||
vector3 Point;
|
||||
vector3 Normal;
|
||||
float tu, tv;
|
||||
};
|
||||
|
||||
class TMaterialColor
|
||||
{
|
||||
public:
|
||||
TMaterialColor() {};
|
||||
TMaterialColor(char V)
|
||||
{
|
||||
r = g = b = V;
|
||||
};
|
||||
// TMaterialColor(double R, double G, double B)
|
||||
TMaterialColor(char R, char G, char B)
|
||||
{
|
||||
r = R;
|
||||
g = G;
|
||||
b = B;
|
||||
};
|
||||
|
||||
char r, g, b;
|
||||
};
|
||||
|
||||
/*
|
||||
struct TMaterial
|
||||
{
|
||||
int ID;
|
||||
AnsiString Name;
|
||||
//McZapkie-240702: lepiej uzywac wartosci float do opisu koloru bo funkcje opengl chyba tego na ogol
|
||||
uzywaja
|
||||
float Ambient[4];
|
||||
float Diffuse[4];
|
||||
float Specular[4];
|
||||
float Transparency;
|
||||
GLuint TextureID;
|
||||
};
|
||||
*/
|
||||
/*
|
||||
struct THitBoxContainer
|
||||
{
|
||||
TPlane Planes[6];
|
||||
int Index;
|
||||
inline void Reset() { Planes[0]= TPlane(vector3(0,0,0),0.0f); };
|
||||
inline bool Inside(vector3 Point)
|
||||
{
|
||||
bool Hit= true;
|
||||
|
||||
if (Planes[0].Defined())
|
||||
for (int i=0; i<6; i++)
|
||||
{
|
||||
if (Planes[i].GetSide(Point)>0)
|
||||
{
|
||||
Hit= false;
|
||||
break;
|
||||
};
|
||||
|
||||
}
|
||||
else return(false);
|
||||
return(Hit);
|
||||
};
|
||||
};
|
||||
*/
|
||||
|
||||
/* Ra: tego nie będziemy już używać, bo można wycisnąć więcej
|
||||
typedef enum
|
||||
{smt_Unknown, //nieznany
|
||||
smt_Mesh, //siatka
|
||||
smt_Point,
|
||||
smt_FreeSpotLight, //punkt świetlny
|
||||
smt_Text, //generator tekstu
|
||||
smt_Stars //wiele punktów świetlnych
|
||||
} TSubModelType;
|
||||
*/
|
||||
// Ra: specjalne typy submodeli, poza tym GL_TRIANGLES itp.
|
||||
const int TP_ROTATOR = 256;
|
||||
const int TP_FREESPOTLIGHT = 257;
|
||||
@@ -134,6 +58,7 @@ class TSubModel
|
||||
//m7todo: zrobić normalną serializację
|
||||
|
||||
friend class opengl_renderer;
|
||||
friend class TModel3d; // temporary workaround. TODO: clean up class content/hierarchy
|
||||
|
||||
private:
|
||||
int iNext;
|
||||
@@ -160,7 +85,6 @@ private:
|
||||
union
|
||||
{ // transform, nie każdy submodel musi mieć
|
||||
float4x4 *fMatrix; // pojedyncza precyzja wystarcza
|
||||
// matrix4x4 *dMatrix; //do testu macierz podwójnej precyzji
|
||||
int iMatrix; // w pliku binarnym jest numer matrycy
|
||||
};
|
||||
int iNumVerts; // ilość wierzchołków (1 dla FreeSpotLight)
|
||||
@@ -188,21 +112,19 @@ private:
|
||||
TSubModel *Next;
|
||||
TSubModel *Child;
|
||||
intptr_t iVboPtr;
|
||||
geometrychunk_handle m_chunk; // geometry of the submodel
|
||||
texture_manager::size_type TextureID; // numer tekstury, -1 wymienna, 0 brak
|
||||
bool bWire; // nie używane, ale wczytywane
|
||||
// short TexAlpha; //Ra: nie używane już
|
||||
GLuint uiDisplayList; // roboczy numer listy wyświetlania
|
||||
float Opacity; // nie używane, ale wczytywane //m7todo: wywalić to
|
||||
// ABu: te same zmienne, ale zdublowane dla Render i RenderAlpha,
|
||||
// bo sie chrzanilo przemieszczanie obiektow.
|
||||
// Ra: już się nie chrzani
|
||||
float f_Angle;
|
||||
float3 v_RotateAxis;
|
||||
float3 v_Angles;
|
||||
|
||||
public: // chwilowo
|
||||
float3 v_TransVector;
|
||||
float8 *Vertices; // roboczy wskaźnik - wczytanie T3D do VBO
|
||||
basic_vertex *Vertices; // roboczy wskaźnik - wczytanie T3D do VBO
|
||||
size_t iAnimOwner; // roboczy numer egzemplarza, który ustawił animację
|
||||
TAnimType b_aAnim; // kody animacji oddzielnie, bo zerowane
|
||||
public:
|
||||
@@ -212,14 +134,10 @@ public:
|
||||
smLetter; // wskaźnik na tablicę submdeli do generoania tekstu (docelowo zapisać do E3D)
|
||||
TSubModel *Parent; // nadrzędny, np. do wymnażania macierzy
|
||||
int iVisible; // roboczy stan widoczności
|
||||
// AnsiString asTexture; //robocza nazwa tekstury do zapisania w pliku binarnym
|
||||
// AnsiString asName; //robocza nazwa
|
||||
std::string pTexture; // robocza nazwa tekstury do zapisania w pliku binarnym
|
||||
std::string pName; // robocza nazwa
|
||||
private:
|
||||
// int SeekFaceNormal(DWORD *Masks, int f,DWORD dwMask,vector3 *pt,GLVERTEX
|
||||
// *Vertices);
|
||||
int SeekFaceNormal(unsigned int *Masks, int f, unsigned int dwMask, float3 *pt, float8 *Vertices);
|
||||
int SeekFaceNormal(unsigned int *Masks, int f, unsigned int dwMask, glm::vec3 *pt, basic_vertex *Vertices);
|
||||
void RaAnimation(TAnimType a);
|
||||
|
||||
public:
|
||||
@@ -235,18 +153,10 @@ public:
|
||||
int Load(cParser &Parser, TModel3d *Model, int Pos, bool dynamic);
|
||||
void ChildAdd(TSubModel *SubModel);
|
||||
void NextAdd(TSubModel *SubModel);
|
||||
TSubModel * NextGet()
|
||||
{
|
||||
return Next;
|
||||
};
|
||||
TSubModel * ChildGet()
|
||||
{
|
||||
return Child;
|
||||
};
|
||||
TSubModel * NextGet() { return Next; };
|
||||
TSubModel * ChildGet() { return Child; };
|
||||
int TriangleAdd(TModel3d *m, texture_manager::size_type tex, int tri);
|
||||
float8 * TrianglePtr(int tex, int pos, int *la, int *ld, int *ls);
|
||||
// float8* TrianglePtr(const char *tex,int tri);
|
||||
// void SetRotate(vector3 vNewRotateAxis,float fNewAngle);
|
||||
basic_vertex * TrianglePtr(int tex, int pos, int *la, int *ld, int *ls);
|
||||
void SetRotate(float3 vNewRotateAxis, float fNewAngle);
|
||||
void SetRotateXYZ(vector3 vNewAngles);
|
||||
void SetRotateXYZ(float3 vNewAngles);
|
||||
@@ -255,18 +165,9 @@ public:
|
||||
void SetRotateIK1(float3 vNewAngles);
|
||||
TSubModel * GetFromName(std::string const &search, bool i = true);
|
||||
TSubModel * GetFromName(char const *search, bool i = true);
|
||||
// inline matrix4x4* GetMatrix() {return dMatrix;};
|
||||
inline float4x4 * GetMatrix()
|
||||
{
|
||||
return fMatrix;
|
||||
};
|
||||
// matrix4x4* GetTransform() {return Matrix;};
|
||||
inline void Hide()
|
||||
{
|
||||
iVisible = 0;
|
||||
};
|
||||
inline float4x4 * GetMatrix() { return fMatrix; };
|
||||
inline void Hide() { iVisible = 0; };
|
||||
void RaArrayFill(CVertNormTex *Vert);
|
||||
// void Render();
|
||||
int FlagsCheck();
|
||||
void WillBeAnimated()
|
||||
{
|
||||
@@ -275,7 +176,7 @@ public:
|
||||
};
|
||||
void InitialRotate(bool doit);
|
||||
void DisplayLists();
|
||||
void BinInit(TSubModel *s, float4x4 *m, float8 *v,
|
||||
void BinInit(TSubModel *s, float4x4 *m, basic_vertex *v,
|
||||
std::vector<std::string> *t, std::vector<std::string> *n, bool dynamic);
|
||||
void ReplacableSet(texture_manager::size_type const *r, int a)
|
||||
{
|
||||
@@ -285,14 +186,8 @@ public:
|
||||
void TextureNameSet(const char *n);
|
||||
void NameSet(const char *n);
|
||||
// Ra: funkcje do budowania terenu z E3D
|
||||
int Flags()
|
||||
{
|
||||
return iFlags;
|
||||
};
|
||||
void UnFlagNext()
|
||||
{
|
||||
iFlags &= 0x00FFFFFF;
|
||||
};
|
||||
int Flags() { return iFlags; };
|
||||
void UnFlagNext() { iFlags &= 0x00FFFFFF; };
|
||||
void ColorsSet(int *a, int *d, int *s);
|
||||
inline float3 Translation1Get()
|
||||
{
|
||||
@@ -323,9 +218,6 @@ class TModel3d : public CMesh
|
||||
friend class opengl_renderer;
|
||||
|
||||
private:
|
||||
// TMaterial *Materials;
|
||||
// int MaterialsCount; //Ra: nie używane
|
||||
// bool TractionPart; //Ra: nie używane
|
||||
TSubModel *Root; // drzewo submodeli
|
||||
int iFlags; // Ra: czy submodele mają przezroczyste tekstury
|
||||
public: // Ra: tymczasowo
|
||||
@@ -338,16 +230,10 @@ private:
|
||||
std::string asBinary; // nazwa pod którą zapisać model binarny
|
||||
std::string m_filename;
|
||||
public:
|
||||
inline TSubModel * GetSMRoot()
|
||||
{
|
||||
return (Root);
|
||||
};
|
||||
// double Radius; //Ra: nie używane
|
||||
inline TSubModel * GetSMRoot() { return (Root); };
|
||||
TModel3d();
|
||||
TModel3d(char *FileName);
|
||||
~TModel3d();
|
||||
TSubModel * GetFromName(const char *sName);
|
||||
// TMaterial* GetMaterialFromName(char *sName);
|
||||
TSubModel * AddToNamed(const char *Name, TSubModel *SubModel);
|
||||
void AddTo(TSubModel *tmp, TSubModel *SubModel);
|
||||
void LoadFromTextFile(std::string const &FileName, bool dynamic);
|
||||
@@ -355,17 +241,9 @@ public:
|
||||
bool LoadFromFile(std::string const &FileName, bool dynamic);
|
||||
void SaveToBinFile(char const *FileName);
|
||||
void BreakHierarhy();
|
||||
// inline int GetSubModelsCount() { return (SubModelsCount); };
|
||||
int Flags() const
|
||||
{
|
||||
return iFlags;
|
||||
};
|
||||
int Flags() const { return iFlags; };
|
||||
void Init();
|
||||
std::string NameGet()
|
||||
{
|
||||
// return Root ? Root->pName : NULL;
|
||||
return m_filename;
|
||||
};
|
||||
std::string NameGet() { return m_filename; };
|
||||
int TerrainCount();
|
||||
TSubModel * TerrainSquare(int n);
|
||||
void TerrainRenderVBO(int n);
|
||||
|
||||
@@ -62,6 +62,8 @@ private:
|
||||
*/
|
||||
};
|
||||
|
||||
typedef std::size_t texture_handle;
|
||||
|
||||
class texture_manager {
|
||||
|
||||
private:
|
||||
|
||||
12
VBO.cpp
12
VBO.cpp
@@ -49,6 +49,9 @@ CMesh::CMesh()
|
||||
#endif
|
||||
m_nVertexCount = -1;
|
||||
m_nVBOVertices = 0; // nie zarezerwowane
|
||||
|
||||
// TODO: bind proper subtype based on the settings
|
||||
m_geometry = std::make_shared<opengl_vbogeometrybank>();
|
||||
};
|
||||
|
||||
CMesh::~CMesh()
|
||||
@@ -107,6 +110,7 @@ void CMesh::Clear()
|
||||
|
||||
bool CMesh::StartVBO()
|
||||
{ // początek rysowania elementów z VBO
|
||||
|
||||
if (m_nVertexCount <= 0)
|
||||
return false; // nie ma nic do rysowania w ten sposób
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
@@ -118,12 +122,15 @@ bool CMesh::StartVBO()
|
||||
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
|
||||
}
|
||||
return true; // można rysować z VBO
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
bool CMesh::StartColorVBO()
|
||||
{ // początek rysowania punktów świecących z VBO
|
||||
|
||||
if (m_nVertexCount <= 0)
|
||||
return false; // nie ma nic do rysowania w ten sposób
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
@@ -134,8 +141,9 @@ bool CMesh::StartColorVBO()
|
||||
glVertexPointer( 3, GL_FLOAT, sizeof( CVertNormTex ), static_cast<char *>( nullptr ) ); // pozycje
|
||||
// glColorPointer(3,GL_UNSIGNED_BYTE,sizeof(CVertNormTex),((char*)NULL)+12); //kolory
|
||||
glColorPointer( 3, GL_FLOAT, sizeof( CVertNormTex ), static_cast<char *>( nullptr ) + 12 ); // kolory
|
||||
return true; // można rysować z VBO
|
||||
}
|
||||
return true; // można rysować z VBO
|
||||
return false;
|
||||
};
|
||||
|
||||
void CMesh::EndVBO()
|
||||
|
||||
22
VBO.h
22
VBO.h
@@ -7,8 +7,9 @@ obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#ifndef VBOH
|
||||
#define VBOH
|
||||
#pragma once
|
||||
|
||||
#include "openglgeometrybank.h"
|
||||
|
||||
#define EU07_USE_OLD_VERTEXBUFFER
|
||||
|
||||
@@ -32,13 +33,6 @@ class CVertNormTex
|
||||
class CMesh
|
||||
{ // wsparcie dla VBO
|
||||
public:
|
||||
int m_nVertexCount; // liczba wierzchołków
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
CVertNormTex *m_pVNT;
|
||||
#else
|
||||
std::vector<CVertNormTex> m_pVNT;
|
||||
#endif
|
||||
unsigned int m_nVBOVertices; // numer VBO z wierzchołkami
|
||||
CMesh();
|
||||
~CMesh();
|
||||
void MakeArray(int n); // tworzenie tablicy z elementami VNT
|
||||
@@ -47,6 +41,14 @@ class CMesh
|
||||
bool StartVBO();
|
||||
void EndVBO();
|
||||
bool StartColorVBO();
|
||||
};
|
||||
|
||||
int m_nVertexCount; // liczba wierzchołków
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
CVertNormTex *m_pVNT;
|
||||
#else
|
||||
std::vector<CVertNormTex> m_pVNT;
|
||||
#endif
|
||||
unsigned int m_nVBOVertices; // numer VBO z wierzchołkami
|
||||
|
||||
std::shared_ptr<geometry_bank> m_geometry;
|
||||
};
|
||||
|
||||
@@ -222,6 +222,9 @@
|
||||
<ClCompile Include="command.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="openglgeometrybank.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Globals.h">
|
||||
@@ -434,6 +437,9 @@
|
||||
<ClInclude Include="version.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="openglgeometrybank.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="maszyna.rc">
|
||||
|
||||
218
openglgeometrybank.cpp
Normal file
218
openglgeometrybank.cpp
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
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/.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openglgeometrybank.h"
|
||||
|
||||
#include "sn_utils.h"
|
||||
|
||||
void
|
||||
basic_vertex::serialize( std::ostream &s ) {
|
||||
|
||||
sn_utils::ls_float32( s, position.x );
|
||||
sn_utils::ls_float32( s, position.y );
|
||||
sn_utils::ls_float32( s, position.z );
|
||||
|
||||
sn_utils::ls_float32( s, normal.x );
|
||||
sn_utils::ls_float32( s, normal.y );
|
||||
sn_utils::ls_float32( s, normal.z );
|
||||
|
||||
sn_utils::ls_float32( s, texture.x );
|
||||
sn_utils::ls_float32( s, texture.y );
|
||||
}
|
||||
|
||||
void
|
||||
basic_vertex::deserialize( std::istream &s ) {
|
||||
|
||||
position.x = sn_utils::ld_float32( s );
|
||||
position.y = sn_utils::ld_float32( s );
|
||||
position.z = sn_utils::ld_float32( s );
|
||||
|
||||
normal.x = sn_utils::ld_float32( s );
|
||||
normal.y = sn_utils::ld_float32( s );
|
||||
normal.z = sn_utils::ld_float32( s );
|
||||
|
||||
texture.x = sn_utils::ld_float32( s );
|
||||
texture.y = sn_utils::ld_float32( s );
|
||||
}
|
||||
|
||||
// generic geometry bank class, allows storage, update and drawing of geometry chunks
|
||||
|
||||
// creates a new geometry chunk of specified type from supplied vertex data. returns: handle to the chunk
|
||||
geometrychunk_handle
|
||||
geometry_bank::create( vertex_array &Vertices, int const Datatype ) {
|
||||
|
||||
if( true == Vertices.empty() ) { return NULL; }
|
||||
|
||||
m_chunks.emplace_back( Vertices, Datatype );
|
||||
// NOTE: handle is effectively (index into chunk array + 1) this leaves value of 0 to serve as error/empty handle indication
|
||||
return m_chunks.size();
|
||||
}
|
||||
|
||||
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
|
||||
bool
|
||||
geometry_bank::replace( vertex_array &Vertices, geometrychunk_handle const Chunk, std::size_t const Offset ) {
|
||||
|
||||
if( ( Chunk == 0 ) || ( Chunk > m_chunks.size() ) ) { return false; }
|
||||
|
||||
auto &chunk = m_chunks[ Chunk - 1 ];
|
||||
|
||||
if( ( Offset == 0 )
|
||||
&& ( Vertices.size() == chunk.vertices.size() ) ) {
|
||||
// check first if we can get away with a simple swap...
|
||||
chunk.vertices.swap( Vertices );
|
||||
}
|
||||
else {
|
||||
// ...otherwise we need to do some legwork
|
||||
// NOTE: if the offset is larger than existing size of the chunk, it'll bridge the gap with 'blank' vertices
|
||||
// TBD: we could bail out with an error instead if such request occurs
|
||||
chunk.vertices.resize( Offset + Vertices.size(), basic_vertex() );
|
||||
chunk.vertices.insert( std::end( chunk.vertices ), std::begin( Vertices ), std::end( Vertices ) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
vertex_array &
|
||||
geometry_bank::data( geometrychunk_handle const Chunk ) {
|
||||
|
||||
return m_chunks.at( Chunk - 1 ).vertices;
|
||||
}
|
||||
|
||||
// opengl vbo-based variant of the geometry bank
|
||||
|
||||
GLuint opengl_vbogeometrybank::m_activebuffer{ NULL }; // buffer bound currently on the opengl end, if any
|
||||
|
||||
// creates a new geometry chunk of specified type from supplied vertex data. returns: handle to the chunk
|
||||
geometrychunk_handle
|
||||
opengl_vbogeometrybank::create( vertex_array &Vertices, int const Datatype ) {
|
||||
|
||||
auto const handle = geometry_bank::create( Vertices, Datatype );
|
||||
if( handle == NULL ) {
|
||||
// if we didn't get anything, bail early
|
||||
return handle;
|
||||
}
|
||||
// adding a chunk means we'll be (re)building the buffer, which will fill the chunk records, amongst other things
|
||||
// so we don't need to initialize the values here
|
||||
m_chunkrecords.emplace_back( chunk_record() );
|
||||
// kiss the existing buffer goodbye, new overall data size means we'll be making a new one
|
||||
delete_buffer();
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
|
||||
bool
|
||||
opengl_vbogeometrybank::replace( vertex_array &Vertices, geometrychunk_handle const Chunk, std::size_t const Offset ) {
|
||||
|
||||
auto const result = geometry_bank::replace( Vertices, Chunk, Offset );
|
||||
if( false == result ) {
|
||||
// if nothing happened we can bail out early
|
||||
return result;
|
||||
}
|
||||
auto &chunkrecord = m_chunkrecords[ Chunk - 1 ];
|
||||
chunkrecord.is_good = false;
|
||||
// if the overall length of the chunk didn't change we can get away with reusing the old buffer...
|
||||
if( m_chunks[ Chunk - 1 ].vertices.size() != chunkrecord.size ) {
|
||||
// ...but otherwise we'll need to allocate a new one
|
||||
// TBD: we could keep and reuse the old buffer also if the new chunk is smaller than the old one,
|
||||
// but it'd require some extra tracking and work to keep all chunks up to date; also wasting vram; may be not worth it?
|
||||
delete_buffer();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// draws geometry stored in specified chunk
|
||||
void
|
||||
opengl_vbogeometrybank::draw( geometrychunk_handle const Chunk ) {
|
||||
|
||||
if( m_buffer == NULL ) {
|
||||
// if there's no buffer, we'll have to make one
|
||||
// NOTE: this isn't exactly optimal in terms of ensuring the gfx card doesn't stall waiting for the data
|
||||
// may be better to initiate upload earlier (during update phase) and trust this effort won't go to waste
|
||||
if( true == m_chunks.empty() ) { return; }
|
||||
|
||||
std::size_t datasize{ 0 };
|
||||
auto &chunkrecord = m_chunkrecords.begin();
|
||||
for( auto &chunk : m_chunks ) {
|
||||
// fill all chunk records, based on the chunk data
|
||||
chunkrecord->offset = datasize;
|
||||
chunkrecord->size = chunk.vertices.size();
|
||||
datasize += chunkrecord->size;
|
||||
++chunkrecord;
|
||||
}
|
||||
// the odds for all created chunks to get replaced with empty ones are quite low, but the possibility does exist
|
||||
if( datasize == 0 ) { return; }
|
||||
// try to set up the buffer we need
|
||||
::glGenBuffers( 1, &m_buffer );
|
||||
bind_buffer();
|
||||
// NOTE: we're using static_draw since it's generally true for all we have implemented at the moment
|
||||
// TODO: allow to specify usage hint at the object creation, and pass it here
|
||||
::glBufferData(
|
||||
GL_ARRAY_BUFFER,
|
||||
datasize * sizeof( basic_vertex ),
|
||||
nullptr,
|
||||
GL_STATIC_DRAW );
|
||||
m_buffercapacity = datasize;
|
||||
}
|
||||
// actual draw procedure starts here
|
||||
// setup...
|
||||
if( m_activebuffer != m_buffer ) {
|
||||
bind_buffer();
|
||||
}
|
||||
auto &chunkrecord = m_chunkrecords[ Chunk - 1 ];
|
||||
auto const &chunk = m_chunks[ Chunk - 1 ];
|
||||
if( false == chunkrecord.is_good ) {
|
||||
// we may potentially need to upload new buffer data before we can draw it
|
||||
::glBufferSubData(
|
||||
GL_ARRAY_BUFFER,
|
||||
chunkrecord.offset * sizeof( basic_vertex ),
|
||||
chunkrecord.size * sizeof( basic_vertex ),
|
||||
chunk.vertices.data() );
|
||||
chunkrecord.is_good = true;
|
||||
}
|
||||
// ...render...
|
||||
::glDrawArrays( chunk.type, chunkrecord.offset, chunkrecord.size );
|
||||
// ...post-render cleanup
|
||||
/*
|
||||
::glDisableClientState( GL_VERTEX_ARRAY );
|
||||
::glDisableClientState( GL_NORMAL_ARRAY );
|
||||
::glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
::glBindBuffer( GL_ARRAY_BUFFER, 0 ); m_activebuffer = 0;
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
opengl_vbogeometrybank::bind_buffer() {
|
||||
|
||||
::glBindBuffer( GL_ARRAY_BUFFER, m_buffer );
|
||||
// TODO: allow specifying other vertex data setups
|
||||
::glVertexPointer( 3, GL_FLOAT, sizeof( basic_vertex ), static_cast<char *>( nullptr ) );
|
||||
::glNormalPointer( GL_FLOAT, sizeof( basic_vertex ), static_cast<char *>( nullptr ) + sizeof(float) * 3 ); // normalne
|
||||
::glTexCoordPointer( 2, GL_FLOAT, sizeof( basic_vertex ), static_cast<char *>( nullptr ) + 24 ); // wierzchołki
|
||||
// TODO: allow specifying other vertex data setups, either in the draw() parameters or during chunk or buffer creation
|
||||
::glEnableClientState( GL_VERTEX_ARRAY );
|
||||
::glEnableClientState( GL_NORMAL_ARRAY );
|
||||
::glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
m_activebuffer = m_buffer;
|
||||
}
|
||||
|
||||
void
|
||||
opengl_vbogeometrybank::delete_buffer() {
|
||||
|
||||
if( m_buffer != NULL ) {
|
||||
|
||||
::glDeleteBuffers( 1, &m_buffer );
|
||||
if( m_activebuffer == m_buffer ) {
|
||||
m_activebuffer = NULL;
|
||||
}
|
||||
m_buffer = NULL;
|
||||
m_buffercapacity = 0;
|
||||
}
|
||||
}
|
||||
122
openglgeometrybank.h
Normal file
122
openglgeometrybank.h
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
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 <vector>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include "GL/glew.h"
|
||||
#ifdef _WINDOWS
|
||||
#include "GL/wglew.h"
|
||||
#endif
|
||||
|
||||
struct basic_vertex {
|
||||
glm::vec3 position; // 3d space
|
||||
glm::vec3 normal; // 3d space
|
||||
glm::vec2 texture; // uv space
|
||||
|
||||
void serialize( std::ostream& );
|
||||
void deserialize( std::istream& );
|
||||
};
|
||||
|
||||
typedef std::vector<basic_vertex> vertex_array;
|
||||
|
||||
// generic geometry bank class, allows storage, update and drawing of geometry chunks
|
||||
|
||||
typedef std::size_t geometrychunk_handle;
|
||||
|
||||
class geometry_bank {
|
||||
|
||||
public:
|
||||
// types:
|
||||
|
||||
// constructors:
|
||||
|
||||
// destructor:
|
||||
virtual
|
||||
~geometry_bank() { ; }
|
||||
|
||||
// methods:
|
||||
// creates a new geometry chunk of specified type from supplied vertex data. returns: handle to the chunk or NULL
|
||||
virtual
|
||||
geometrychunk_handle
|
||||
create( vertex_array &Vertices, int const Datatype );
|
||||
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
|
||||
virtual
|
||||
bool
|
||||
replace( vertex_array &Vertices, geometrychunk_handle const Chunk, std::size_t const Offset = 0 );
|
||||
// draws geometry stored in specified chunk
|
||||
virtual
|
||||
void
|
||||
draw( geometrychunk_handle const Chunk ) = 0;
|
||||
// draws geometry stored in supplied list of chunks
|
||||
template <typename _Iterator>
|
||||
void
|
||||
draw( _Iterator First, _Iterator Last ) { while( First != Last ) { draw( *First ); ++First; } }
|
||||
vertex_array &
|
||||
data( geometrychunk_handle const Chunk );
|
||||
|
||||
protected:
|
||||
// types:
|
||||
struct geometry_chunk {
|
||||
int type; // kind of geometry used by the chunk
|
||||
vertex_array vertices; // geometry data
|
||||
|
||||
geometry_chunk( vertex_array &Vertices, int const Datatype ) :
|
||||
vertices( Vertices ), type( Datatype )
|
||||
{}
|
||||
};
|
||||
|
||||
typedef std::vector<geometry_chunk> geometrychunk_sequence;
|
||||
|
||||
// members:
|
||||
geometrychunk_sequence m_chunks;
|
||||
|
||||
};
|
||||
|
||||
// opengl vbo-based variant of the geometry bank
|
||||
|
||||
class opengl_vbogeometrybank : public geometry_bank {
|
||||
|
||||
public:
|
||||
// methods:
|
||||
// creates a new geometry chunk of specified type from supplied vertex data. returns: handle to the chunk or NULL
|
||||
geometrychunk_handle
|
||||
create( vertex_array &Vertices, int const Datatype );
|
||||
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
|
||||
bool
|
||||
replace( vertex_array &Vertices, geometrychunk_handle const Chunk, std::size_t const Offset = 0 );
|
||||
// draws geometry stored in specified chunk
|
||||
void
|
||||
draw( geometrychunk_handle const Chunk );
|
||||
|
||||
private:
|
||||
// types:
|
||||
struct chunk_record{
|
||||
std::size_t offset{ 0 }; // beginning of the chunk data as offset from the beginning of the last established buffer
|
||||
std::size_t size{ 0 }; // size of the chunk in the last established buffer
|
||||
bool is_good{ false }; // true if local content of the chunk matches the data on the opengl end
|
||||
};
|
||||
|
||||
typedef std::vector<chunk_record> chunkrecord_sequence;
|
||||
|
||||
// methods:
|
||||
void
|
||||
bind_buffer();
|
||||
void
|
||||
delete_buffer();
|
||||
|
||||
// members:
|
||||
static GLuint m_activebuffer; // buffer bound currently on the opengl end, if any
|
||||
GLuint m_buffer{ NULL }; // id of the buffer holding data on the opengl end
|
||||
std::size_t m_buffercapacity{ 0 }; // total capacity of the last established buffer
|
||||
chunkrecord_sequence m_chunkrecords; // helper data for all stored geometry chunks, in matching order
|
||||
|
||||
};
|
||||
22
renderer.cpp
22
renderer.cpp
@@ -775,11 +775,12 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, double
|
||||
|
||||
// TODO: unify the render code after generic buffers are in place
|
||||
// setup
|
||||
/*
|
||||
if( Global::bUseVBO ) {
|
||||
if( false == Model->StartVBO() )
|
||||
return false;
|
||||
}
|
||||
|
||||
*/
|
||||
Model->Root->ReplacableSet(
|
||||
( Material != nullptr ?
|
||||
Material->replacable_skins :
|
||||
@@ -793,7 +794,7 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, double
|
||||
|
||||
// post-render cleanup
|
||||
if( Global::bUseVBO ) {
|
||||
Model->EndVBO();
|
||||
// Model->EndVBO();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -857,7 +858,10 @@ opengl_renderer::Render( TSubModel *Submodel ) {
|
||||
|
||||
// main draw call. TODO: generic buffer base class, specialized for vbo, dl etc
|
||||
if( Global::bUseVBO ) {
|
||||
/*
|
||||
::glDrawArrays( Submodel->eType, Submodel->iVboPtr, Submodel->iNumVerts );
|
||||
*/
|
||||
Submodel->pRoot->m_geometry->draw( Submodel->m_chunk );
|
||||
}
|
||||
else {
|
||||
::glCallList( Submodel->uiDisplayList );
|
||||
@@ -898,7 +902,10 @@ opengl_renderer::Render( TSubModel *Submodel ) {
|
||||
|
||||
// main draw call. TODO: generic buffer base class, specialized for vbo, dl etc
|
||||
if( Global::bUseVBO ) {
|
||||
/*
|
||||
::glDrawArrays( GL_POINTS, Submodel->iVboPtr, Submodel->iNumVerts );
|
||||
*/
|
||||
Submodel->pRoot->m_geometry->draw( Submodel->m_chunk );
|
||||
}
|
||||
else {
|
||||
::glCallList( Submodel->uiDisplayList );
|
||||
@@ -921,6 +928,7 @@ opengl_renderer::Render( TSubModel *Submodel ) {
|
||||
|
||||
// main draw call. TODO: generic buffer base class, specialized for vbo, dl etc
|
||||
if( Global::bUseVBO ) {
|
||||
/*
|
||||
// NOTE: we're doing manual switch to color vbo setup, because there doesn't seem to be any convenient way available atm
|
||||
// TODO: implement easier way to go about it
|
||||
::glDisableClientState( GL_NORMAL_ARRAY );
|
||||
@@ -933,6 +941,7 @@ opengl_renderer::Render( TSubModel *Submodel ) {
|
||||
::glDisableClientState( GL_COLOR_ARRAY );
|
||||
::glEnableClientState( GL_NORMAL_ARRAY );
|
||||
::glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
*/
|
||||
}
|
||||
else {
|
||||
::glCallList( Submodel->uiDisplayList );
|
||||
@@ -1298,11 +1307,12 @@ opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, d
|
||||
|
||||
// TODO: unify the render code after generic buffers are in place
|
||||
// setup
|
||||
/*
|
||||
if( Global::bUseVBO ) {
|
||||
if( false == Model->StartVBO() )
|
||||
return false;
|
||||
}
|
||||
|
||||
*/
|
||||
Model->Root->ReplacableSet(
|
||||
( Material != nullptr ?
|
||||
Material->replacable_skins :
|
||||
@@ -1315,10 +1325,11 @@ opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, d
|
||||
Render_Alpha( Model->Root );
|
||||
|
||||
// post-render cleanup
|
||||
/*
|
||||
if( Global::bUseVBO ) {
|
||||
Model->EndVBO();
|
||||
}
|
||||
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1378,7 +1389,10 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
|
||||
|
||||
// main draw call. TODO: generic buffer base class, specialized for vbo, dl etc
|
||||
if( Global::bUseVBO ) {
|
||||
/*
|
||||
::glDrawArrays( Submodel->eType, Submodel->iVboPtr, Submodel->iNumVerts );
|
||||
*/
|
||||
Submodel->pRoot->m_geometry->draw( Submodel->m_chunk );
|
||||
}
|
||||
else {
|
||||
::glCallList( Submodel->uiDisplayList );
|
||||
|
||||
Reference in New Issue
Block a user