diff --git a/AnimModel.cpp b/AnimModel.cpp index a5303f08..0e183997 100644 --- a/AnimModel.cpp +++ b/AnimModel.cpp @@ -606,16 +606,16 @@ int TAnimModel::Flags() //----------------------------------------------------------------------------- // 2011-03-16 funkcje renderowania z możliwością pochylania obiektów //----------------------------------------------------------------------------- -void TAnimModel::Render( vector3 *vPosition ) { +void TAnimModel::Render( vector3 const &Position ) { RaAnimate(); // jednorazowe przeliczenie animacji RaPrepare(); if( pModel ) // renderowanie rekurencyjne submodeli - GfxRenderer.Render( pModel, Material(), *vPosition, vAngle ); + GfxRenderer.Render( pModel, Material(), Position, vAngle ); }; -void TAnimModel::RenderAlpha( vector3 *vPosition ) { +void TAnimModel::RenderAlpha( vector3 const &Position ) { RaPrepare(); if( pModel ) // renderowanie rekurencyjne submodeli - GfxRenderer.Render_Alpha( pModel, Material(), *vPosition, vAngle ); + GfxRenderer.Render_Alpha( pModel, Material(), Position, vAngle ); }; //--------------------------------------------------------------------------- diff --git a/AnimModel.h b/AnimModel.h index 760669e8..36fa9c48 100644 --- a/AnimModel.h +++ b/AnimModel.h @@ -161,8 +161,8 @@ class TAnimModel bool Load(cParser *parser, bool ter = false); TAnimContainer * AddContainer(char *pName); TAnimContainer * GetContainer(char *pName); - void Render( vector3 *vPosition ); - void RenderAlpha( vector3 *vPosition ); + void Render( vector3 const &Position ); + void RenderAlpha( vector3 const &Position ); int Flags(); void RaAnglesSet(double a, double b, double c) { diff --git a/Camera.cpp b/Camera.cpp index 06b38254..b1354746 100644 --- a/Camera.cpp +++ b/Camera.cpp @@ -410,21 +410,21 @@ bool TCamera::SetMatrix() return true; } -bool TCamera::SetMatrix( glm::mat4 &Matrix ) { +bool TCamera::SetMatrix( glm::dmat4 &Matrix ) { - Matrix = glm::rotate( Matrix, (float)-Roll, glm::vec3( 0.0f, 0.0f, 1.0f ) ); // po wyłączeniu tego kręci się pojazd, a sceneria nie - Matrix = glm::rotate( Matrix, (float)-Pitch, glm::vec3( 1.0f, 0.0f, 0.0f ) ); - Matrix = glm::rotate( Matrix, (float)-Yaw, glm::vec3( 0.0f, 1.0f, 0.0f ) ); // w zewnętrznym widoku: kierunek patrzenia + Matrix = glm::rotate( Matrix, -Roll, glm::dvec3( 0.0, 0.0, 1.0 ) ); // po wyłączeniu tego kręci się pojazd, a sceneria nie + Matrix = glm::rotate( Matrix, -Pitch, glm::dvec3( 1.0, 0.0, 0.0 ) ); + Matrix = glm::rotate( Matrix, -Yaw, glm::dvec3( 0.0, 1.0, 0.0 ) ); // w zewnętrznym widoku: kierunek patrzenia if( Type == tp_Follow ) { Matrix *= glm::lookAt( - glm::vec3( Pos.x, Pos.y, Pos.z ), - glm::vec3( LookAt.x, LookAt.y, LookAt.z ), - glm::vec3( vUp.x, vUp.y, vUp.z ) ); + glm::dvec3( Pos.x, Pos.y, Pos.z ), + glm::dvec3( LookAt.x, LookAt.y, LookAt.z ), + glm::dvec3( vUp.x, vUp.y, vUp.z ) ); } else { - Matrix = glm::translate( Matrix, glm::vec3( -Pos.x, -Pos.y, -Pos.z ) ); // nie zmienia kierunku patrzenia + Matrix = glm::translate( Matrix, glm::dvec3( -Pos.x, -Pos.y, -Pos.z ) ); // nie zmienia kierunku patrzenia } Global::SetCameraPosition( Pos ); // było +pOffset diff --git a/Camera.h b/Camera.h index c9ab5e05..760a9294 100644 --- a/Camera.h +++ b/Camera.h @@ -58,7 +58,7 @@ class TCamera void Update(); vector3 GetDirection(); bool SetMatrix(); - bool SetMatrix(glm::mat4 &Matrix); + bool SetMatrix(glm::dmat4 &Matrix); void SetCabMatrix( vector3 &p ); void RaLook(); void Stop(); diff --git a/Ground.cpp b/Ground.cpp index e4a6f45d..fff7c1ed 100644 --- a/Ground.cpp +++ b/Ground.cpp @@ -248,43 +248,6 @@ void TGroundNode::InitNormals() } } -void TGroundNode::MoveMe(vector3 pPosition) -{ // przesuwanie obiektów scenerii o wektor w celu redukcji trzęsienia - pCenter += pPosition; - switch (iType) - { - case TP_TRACTION: - hvTraction->pPoint1 += pPosition; - hvTraction->pPoint2 += pPosition; - hvTraction->pPoint3 += pPosition; - hvTraction->pPoint4 += pPosition; - hvTraction->Optimize(); - break; - case TP_MODEL: - case TP_DYNAMIC: - case TP_MEMCELL: - case TP_EVLAUNCH: - break; - case TP_TRACK: - pTrack->MoveMe(pPosition); - break; - case TP_SOUND: // McZapkie - dzwiek zapetlony w zaleznosci od odleglosci - tsStaticSound->vSoundPosition += pPosition; - break; - case GL_LINES: - case GL_LINE_STRIP: - case GL_LINE_LOOP: - for (int i = 0; i < iNumPts; i++) - Points[i] += pPosition; - ResourceManager::Unregister(this); - break; - default: - for (int i = 0; i < iNumVerts; i++) - Vertices[i].Point += pPosition; - ResourceManager::Unregister(this); - } -} - void TGroundNode::RaRenderVBO() { // renderowanie z domyslnego bufora VBO glColor3ub(Diffuse[0], Diffuse[1], Diffuse[2]); @@ -309,7 +272,10 @@ void TGroundNode::Compile(bool many) { glBegin(iType); for (int i = 0; i < iNumPts; ++i) - glVertex3dv(&Points[i].x); + glVertex3d( + Points[i].x - m_rootposition.x, + Points[i].y - m_rootposition.y, + Points[i].z - m_rootposition.z ); glEnd(); } else if (iType == GL_TRIANGLE_STRIP || iType == GL_TRIANGLE_FAN || iType == GL_TRIANGLES) @@ -323,9 +289,14 @@ void TGroundNode::Compile(bool many) for (int i = 0; i < iNumVerts; ++i) { glNormal3dv(&Vertices[i].Normal.x); - glTexCoord2f(Vertices[i].tu, Vertices[i].tv); - glVertex3dv(&Vertices[i].Point.x); - }; + glTexCoord2f( + Vertices[i].tu, + Vertices[i].tv); + glVertex3d( + Points[i].x - m_rootposition.x, + Points[i].y - m_rootposition.y, + Points[i].z - m_rootposition.z ); + } glEnd(); } else if (iType == TP_MESH) @@ -408,6 +379,9 @@ void TSubRect::NodeAdd(TGroundNode *Node) // nRenderAlpha - lista grup renderowanych z własnych VBO albo DL z przezroczystością // nRenderWires - lista grup renderowanych z własnych VBO albo DL - druty i linie // nMeshed - obiekty do pogrupowania wg tekstur + + Node->m_rootposition = Math3D::vector3( m_area.center.x, m_area.center.y, m_area.center.z ) ; + switch (Node->iType) { case TP_SOUND: // te obiekty są sprawdzanie niezależnie od kierunku patrzenia @@ -418,11 +392,11 @@ void TSubRect::NodeAdd(TGroundNode *Node) case TP_TRACK: // TODO: tory z cieniem (tunel, canyon) też dać bez łączenia? ++iTracks; // jeden tor więcej Node->pTrack->RaOwnerSet(this); // do którego sektora ma zgłaszać animację - // if (Global::bUseVBO?false:!Node->pTrack->IsGroupable()) - if (Global::bUseVBO ? true : - !Node->pTrack->IsGroupable()) // TODO: tymczasowo dla VBO wyłączone - RaNodeAdd( - Node); // tory ruchome nie są grupowane przy Display Lists (wymagają odświeżania DL) + if( ( true == Global::bUseVBO ) + || ( false == Node->pTrack->IsGroupable() ) ) { + // tory ruchome nie są grupowane przy Display Lists (wymagają odświeżania DL) + RaNodeAdd( Node ); + } else { // tory nieruchome mogą być pogrupowane wg tekstury, przy VBO wszystkie Node->TextureID = Node->pTrack->TextureGet(0); // pobranie tekstury do sortowania @@ -800,9 +774,9 @@ void TSubRect::LoadNodes() case GL_TRIANGLES: for (i = 0; i < n->iNumVerts; ++i) { // Ra: trójkąty można od razu wczytywać do takich tablic... to może poczekać - m_pVNT[n->iVboPtr + i].x = n->Vertices[i].Point.x; - m_pVNT[n->iVboPtr + i].y = n->Vertices[i].Point.y; - m_pVNT[n->iVboPtr + i].z = n->Vertices[i].Point.z; + m_pVNT[n->iVboPtr + i].x = n->Vertices[i].Point.x - n->m_rootposition.x; + m_pVNT[n->iVboPtr + i].y = n->Vertices[i].Point.y - n->m_rootposition.y; + m_pVNT[n->iVboPtr + i].z = n->Vertices[i].Point.z - n->m_rootposition.z; m_pVNT[n->iVboPtr + i].nx = n->Vertices[i].Normal.x; m_pVNT[n->iVboPtr + i].ny = n->Vertices[i].Normal.y; m_pVNT[n->iVboPtr + i].nz = n->Vertices[i].Normal.z; @@ -815,9 +789,9 @@ void TSubRect::LoadNodes() case GL_LINE_LOOP: for (i = 0; i < n->iNumPts; ++i) { - m_pVNT[n->iVboPtr + i].x = n->Points[i].x; - m_pVNT[n->iVboPtr + i].y = n->Points[i].y; - m_pVNT[n->iVboPtr + i].z = n->Points[i].z; + m_pVNT[n->iVboPtr + i].x = n->Points[i].x - n->m_rootposition.x; + m_pVNT[n->iVboPtr + i].y = n->Points[i].y - n->m_rootposition.y; + m_pVNT[n->iVboPtr + i].z = n->Points[i].z - n->m_rootposition.z; // miejsce w tablicach normalnych i teksturowania się marnuje... } break; @@ -833,7 +807,7 @@ void TSubRect::LoadNodes() case TP_TRACTION: if( n->iNumVerts ) { // druty mogą być niewidoczne...? #ifdef EU07_USE_OLD_VERTEXBUFFER - n->hvTraction->RaArrayFill( m_pVNT + n->iVboPtr ); + n->hvTraction->RaArrayFill( m_pVNT + n->iVboPtr, n->m_rootposition ); #else n->hvTraction->RaArrayFill( m_pVNT.data() + n->iVboPtr ); #endif @@ -960,12 +934,14 @@ TGroundRect::Init() { float const subrectsize = 1000.0f / iNumSubRects; for( int column = 0; column < iNumSubRects; ++column ) { for( int row = 0; row < iNumSubRects; ++row ) { - auto &area = FastGetRect(column, row)->m_area; + auto &area = SafeGetRect(column, row)->m_area; area.center = m_area.center - - float3( 500.0f, 0.0f, 500.0f ) // 'upper left' corner of rectangle - + float3( subrectsize * 0.5f, 0.0f, subrectsize * 0.5f ) // center of sub-rectangle - + float3( subrectsize * column, 0.0f, subrectsize * row ); + - glm::vec3( 500.0f, 0.0f, 500.0f ) // 'upper left' corner of rectangle + + glm::vec3( subrectsize * 0.5f, 0.0f, subrectsize * 0.5f ) // center of sub-rectangle + + glm::vec3( subrectsize * column, 0.0f, subrectsize * row ); + // NOTE: the actual coordinates get swapped, as they're swapped in rest of the code :x + area.center = glm::vec3( area.center.z, area.center.y, area.center.x ); area.radius = subrectsize * M_SQRT2; } } @@ -1051,17 +1027,17 @@ TGround::TGround() // set bounding area information for ground rectangles float const rectsize = 1000.0f; - float3 const worldcenter( 0.0f, 0.0f, 0.0f ); + glm::vec3 const worldcenter( 0.0f, 0.0f, 0.0f ); for( int column = 0; column < iNumRects; ++column ) { for( int row = 0; row < iNumRects; ++row ) { auto &area = Rects[ column ][ row ].m_area; // NOTE: in current implementation triangles can stick out to ~200m from the area, so we add extra padding - area.radius = 200.0f + rectsize * 0.5f * M_SQRT2; + area.radius = ( rectsize * 0.5f * M_SQRT2 ) + 200.0f; area.center = worldcenter - - float3( (iNumRects / 2) * rectsize, 0.0f, (iNumRects / 2) * rectsize ) // 'upper left' corner of the world - + float3( rectsize * 0.5f, 0.0f, rectsize * 0.5f ) // center of the rectangle - + float3( rectsize * column, 0.0f, rectsize * row ); + - glm::vec3( (iNumRects / 2) * rectsize, 0.0f, (iNumRects / 2) * rectsize ) // 'upper left' corner of the world + + glm::vec3( rectsize * 0.5f, 0.0f, rectsize * 0.5f ) // center of the rectangle + + glm::vec3( rectsize * column, 0.0f, rectsize * row ); } } } @@ -1995,39 +1971,38 @@ void TGround::FirstInit() gr->RaNodeAdd(&Current->nNode[j]); } } - // else if - // ((Current->iType!=GL_TRIANGLES)&&(Current->iType!=GL_TRIANGLE_STRIP)?true - // //~czy trójkąt? - else if ((Current->iType != GL_TRIANGLES) ? - true //~czy trójkąt? - : - (Current->iFlags & 0x20) ? - true //~czy teksturę ma nieprzezroczystą? - : - (Current->fSquareMinRadius != 0.0) ? - true //~czy widoczny z bliska? - : - (Current->fSquareRadius <= 90000.0)) //~czy widoczny z daleka? - GetSubRect(Current->pCenter.x, Current->pCenter.z)->NodeAdd(Current); - else // dodajemy do kwadratu kilometrowego - GetRect(Current->pCenter.x, Current->pCenter.z)->NodeAdd(Current); + else if( ( Current->iType != GL_TRIANGLES ) + || ( Current->iFlags & 0x20 ) + || ( Current->fSquareMinRadius != 0.0 ) + || ( Current->fSquareRadius <= 90000.0 ) ) { + // add to sub-rectangle + GetSubRect( Current->pCenter.x, Current->pCenter.z )->NodeAdd( Current ); + } + else { + // dodajemy do kwadratu kilometrowego + GetRect( Current->pCenter.x, Current->pCenter.z )->NodeAdd( Current ); + } } - // if (Current->iType!=TP_DYNAMIC) - // GetSubRect(Current->pCenter.x,Current->pCenter.z)->AddNode(Current); } } for (i = 0; i < iNumRects; ++i) for (j = 0; j < iNumRects; ++j) Rects[i][j].Optimize(); // optymalizacja obiektów w sektorach + WriteLog("InitNormals OK"); + InitTracks(); //łączenie odcinków ze sobą i przyklejanie eventów WriteLog("InitTracks OK"); + InitTraction(); //łączenie drutów ze sobą WriteLog("InitTraction OK"); + InitEvents(); WriteLog("InitEvents OK"); + InitLaunchers(); WriteLog("InitLaunchers OK"); + WriteLog("FirstInit is done"); }; @@ -2077,13 +2052,14 @@ bool TGround::Init(std::string File) } else if ( ( LastNode->iType == TP_TRACTION ) && ( false == Global::bLoadTraction ) ) SafeDelete(LastNode); // usuwamy druty, jeśli wyłączone + if (LastNode) // dopiero na koniec dopisujemy do tablic if (LastNode->iType != TP_DYNAMIC) { // jeśli nie jest pojazdem - LastNode->nNext = nRootOfType[LastNode->iType]; // ostatni dodany dołączamy - // na końcu nowego - nRootOfType[LastNode->iType] = - LastNode; // ustawienie nowego na początku listy + // ostatni dodany dołączamy na końcu nowego + LastNode->nNext = nRootOfType[LastNode->iType]; + // ustawienie nowego na początku listy + nRootOfType[LastNode->iType] = LastNode; iNumNodes++; } else @@ -2437,10 +2413,6 @@ bool TGround::Init(std::string File) else // jak liczba to na pewno błąd Error("Unrecognized command: " + str); } -/* else if (str == "") - break; -*/ - // LastNode=NULL; token = ""; parser.getTokens(); diff --git a/Ground.h b/Ground.h index ee20b738..ca2aced2 100644 --- a/Ground.h +++ b/Ground.h @@ -122,19 +122,20 @@ public: 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 + // visualization-related data + // TODO: wrap these in a struct, when cleaning objects up union { int iNumVerts; // dla trójkątów int iNumPts; // dla linii int iCount; // dla terenu - // int iState; //Ra: nie używane - dźwięki zapętlone }; - vector3 pCenter; // współrzędne środka do przydzielenia sektora - double fLineThickness; // McZapkie-120702: grubosc linii double fSquareRadius; // kwadrat widoczności do double fSquareMinRadius; // kwadrat widoczności od - // TGroundNode *nMeshGroup; //Ra: obiekt grupujący trójkąty w TSubRect dla tekstury int iVersion; // wersja siatki (do wykonania rekompilacji) // union ? GLuint DisplayListID; // numer siatki DisplayLists @@ -144,6 +145,7 @@ public: int iFlags; // tryb przezroczystości: 0x10-nieprz.,0x20-przezroczysty,0x30-mieszany int Ambient[4], Diffuse[4], Specular[4]; // oświetlenie 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 @@ -154,8 +156,6 @@ public: void InitCenter(); // obliczenie współrzędnych środka void InitNormals(); - void MoveMe(vector3 pPosition); // przesuwanie (nie działa) - // bool Disable(); inline TGroundNode * Find(const std::string &asNameToFind, TGroundNodeType iNodeType) { // wyszukiwanie czołgowe z typem @@ -177,7 +177,7 @@ public: struct bounding_area { - float3 center; // mid point of the rectangle + glm::vec3 center; // mid point of the rectangle float radius{ 0.0f }; // radius of the bounding sphere }; diff --git a/Segment.cpp b/Segment.cpp index 194c3209..c3fdb478 100644 --- a/Segment.cpp +++ b/Segment.cpp @@ -319,7 +319,7 @@ vector3 TSegment::FastGetPoint(double t) return (bCurve ? RaInterpolate(t) : ((1.0 - t) * Point1 + (t)*Point2)); } -int TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale, int iSkip, int iEnd, double fOffsetX, bool Onlypositions, vector3 **p, bool bRender) +int TSegment::RenderLoft( CVertNormTex* &Output, Math3D::vector3 const &Origin, const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale, int iSkip, int iEnd, double fOffsetX, vector3 **p, bool bRender) { // generowanie trójkątów dla odcinka trajektorii ruchu // standardowo tworzy triangle_strip dla prostego albo ich zestaw dla łuku // po modyfikacji - dla ujemnego (iNumShapePoints) w dodatkowych polach tabeli @@ -368,12 +368,10 @@ int TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, int jmm2 = 0.0; } - if( false == Onlypositions ) { - while( tv1 < 0.0 ) { - tv1 += 1.0; - } - tv2 = tv1 - step / fTextureLength; // mapowanie na końcu segmentu + while( tv1 < 0.0 ) { + tv1 += 1.0; } + tv2 = tv1 - step / fTextureLength; // mapowanie na końcu segmentu t = fTsBuffer[ i ]; // szybsze od GetTFromS(s); pos2 = FastGetPoint( t ); @@ -389,30 +387,25 @@ int TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, int for( int j = 0; j < iNumShapePoints; ++j ) { pt = parallel1 * ( jmm1 * ( ShapePoints[ j ].x - fOffsetX ) + m1 * ShapePoints[ j + iNumShapePoints ].x ) + pos1; pt.y += jmm1 * ShapePoints[ j ].y + m1 * ShapePoints[ j + iNumShapePoints ].y; - if( false == Onlypositions ) { - norm = ( jmm1 * ShapePoints[ j ].n.x + m1 * ShapePoints[ j + iNumShapePoints ].n.x ) * parallel1; - norm.y += jmm1 * ShapePoints[ j ].n.y + m1 * ShapePoints[ j + iNumShapePoints ].n.y; - } + pt -= Origin; + norm = ( jmm1 * ShapePoints[ j ].n.x + m1 * ShapePoints[ j + iNumShapePoints ].n.x ) * parallel1; + norm.y += jmm1 * ShapePoints[ j ].n.y + m1 * ShapePoints[ j + iNumShapePoints ].n.y; if( bRender ) { // skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale potrzebować punktów if( Output == nullptr ) { // immediate mode - if( false == Onlypositions ) { - ::glNormal3f( norm.x, norm.y, norm.z ); - ::glTexCoord2f( (jmm1 * ShapePoints[ j ].z + m1 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale, tv1 ); - } + ::glNormal3f( norm.x, norm.y, norm.z ); + ::glTexCoord2f( (jmm1 * ShapePoints[ j ].z + m1 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale, tv1 ); ::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; - if( false == Onlypositions ) { - 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->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; } ++vertexcount; @@ -427,30 +420,25 @@ int TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, int // dla trapezu drugi koniec ma inne współrzędne pt = parallel2 * ( jmm2 * ( ShapePoints[ j ].x - fOffsetX ) + m2 * ShapePoints[ j + iNumShapePoints ].x ) + pos2; pt.y += jmm2 * ShapePoints[ j ].y + m2 * ShapePoints[ j + iNumShapePoints ].y; - if( false == Onlypositions ) { - norm = ( jmm1 * ShapePoints[ j ].n.x + m1 * ShapePoints[ j + iNumShapePoints ].n.x ) * parallel2; - norm.y += jmm1 * ShapePoints[ j ].n.y + m1 * ShapePoints[ j + iNumShapePoints ].n.y; - } + pt -= Origin; + norm = ( jmm1 * ShapePoints[ j ].n.x + m1 * ShapePoints[ j + iNumShapePoints ].n.x ) * parallel2; + norm.y += jmm1 * ShapePoints[ j ].n.y + m1 * ShapePoints[ j + iNumShapePoints ].n.y; if( bRender ) { // skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale potrzebować punktów if( Output == nullptr ) { // immediate mode - if( false == Onlypositions ) { - ::glNormal3f( norm.x, norm.y, norm.z ); - ::glTexCoord2f( (jmm2 * ShapePoints[ j ].z + m2 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale, tv2 ); - } + ::glNormal3f( norm.x, norm.y, norm.z ); + ::glTexCoord2f( (jmm2 * ShapePoints[ j ].z + m2 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale, tv2 ); ::glVertex3f( pt.x, pt.y, pt.z ); } else { Output->x = pt.x; Output->y = pt.y; Output->z = pt.z; - if( false == Onlypositions ) { - 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->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; } ++vertexcount; @@ -470,58 +458,48 @@ int TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, int //łuk z jednym profilem pt = parallel1 * ( ShapePoints[ j ].x - fOffsetX ) + pos1; pt.y += ShapePoints[ j ].y; - if( false == Onlypositions ) { - norm = ShapePoints[ j ].n.x * parallel1; - norm.y += ShapePoints[ j ].n.y; - } + pt -= Origin; + norm = ShapePoints[ j ].n.x * parallel1; + norm.y += ShapePoints[ j ].n.y; if( Output == nullptr ) { // immediate mode - if( false == Onlypositions ) { - ::glNormal3f( norm.x, norm.y, norm.z ); - ::glTexCoord2f( ShapePoints[ j ].z / Texturescale, tv1 ); - } + ::glNormal3f( norm.x, norm.y, norm.z ); + ::glTexCoord2f( ShapePoints[ j ].z / Texturescale, tv1 ); ::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; - if( false == Onlypositions ) { - Output->nx = norm.x; - Output->ny = norm.y; - Output->nz = norm.z; - Output->u = ShapePoints[ j ].z / Texturescale; - Output->v = tv1; - } + Output->nx = norm.x; + Output->ny = norm.y; + Output->nz = norm.z; + Output->u = ShapePoints[ j ].z / Texturescale; + Output->v = tv1; ++Output; } ++vertexcount; pt = parallel2 * ShapePoints[ j ].x + pos2; pt.y += ShapePoints[ j ].y; - if( false == Onlypositions ) { - norm = ShapePoints[ j ].n.x * parallel2; - norm.y += ShapePoints[ j ].n.y; - } + pt -= Origin; + norm = ShapePoints[ j ].n.x * parallel2; + norm.y += ShapePoints[ j ].n.y; if( Output == nullptr ) { // immediate mode - if( false == Onlypositions ) { - ::glNormal3f( norm.x, norm.y, norm.z ); - ::glTexCoord2f( ShapePoints[ j ].z / Texturescale, tv2 ); - } + ::glNormal3f( norm.x, norm.y, norm.z ); + ::glTexCoord2f( ShapePoints[ j ].z / Texturescale, tv2 ); ::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; - if( false == Onlypositions ) { - Output->nx = norm.x; - Output->ny = norm.y; - Output->nz = norm.z; - Output->u = ShapePoints[ j ].z / Texturescale; - Output->v = tv2; - } + Output->nx = norm.x; + Output->ny = norm.y; + Output->nz = norm.z; + Output->u = ShapePoints[ j ].z / Texturescale; + Output->v = tv2; ++Output; } ++vertexcount; @@ -534,9 +512,7 @@ int TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, int } pos1 = pos2; parallel1 = parallel2; - if( false == Onlypositions ) { - tv1 = tv2; - } + tv1 = tv2; } return vertexcount; diff --git a/Segment.h b/Segment.h index 1c4c84ab..25a9875f 100644 --- a/Segment.h +++ b/Segment.h @@ -113,7 +113,7 @@ class TSegment r1 = fRoll1; r2 = fRoll2; } - int RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale = 1.0, int iSkip = 0, int iEnd = 0, double fOffsetX = 0.0, bool Onlypositions = false, vector3 **p = nullptr, bool bRender = true); + int RenderLoft( CVertNormTex* &Output, Math3D::vector3 const &Origin, vector6 const *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale = 1.0, int iSkip = 0, int iEnd = 0, double fOffsetX = 0.0, vector3 **p = nullptr, bool bRender = true); void Render(); inline double GetLength() { diff --git a/Track.cpp b/Track.cpp index b0920ad9..ddb669cc 100644 --- a/Track.cpp +++ b/Track.cpp @@ -1090,6 +1090,9 @@ void TTrack::Compile(GLuint tex) hypot2 = hypot1; normal2 = normal1; } + + auto const origin = pMyNode->m_rootposition; + double roll1, roll2; switch (iCategoryFlag & 15) { @@ -1216,15 +1219,15 @@ void TTrack::Compile(GLuint tex) } if (!tex) GfxRenderer.Bind( TextureID2 ); - Segment->RenderLoft( immediate, bpts1, iTrapezoid ? -4 : 4, fTexLength); + Segment->RenderLoft( immediate, origin, bpts1, iTrapezoid ? -4 : 4, fTexLength); } if (TextureID1) if (tex ? TextureID1 == tex : true) // jeśli pasuje do grupy (tex) { // szyny if (!tex) GfxRenderer.Bind( TextureID1 ); - Segment->RenderLoft( immediate, rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength); - Segment->RenderLoft( immediate, rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength); + Segment->RenderLoft( immediate, origin, rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength); + Segment->RenderLoft( immediate, origin, rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength); } break; case tt_Switch: // dla zwrotnicy dwa razy szyny @@ -1252,31 +1255,31 @@ void TTrack::Compile(GLuint tex) { // zwrotnica prawa if( TextureID1 ) { GfxRenderer.Bind( TextureID1 ); - SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 ); // prawa iglica - SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, rpts1, nnumPts, fTexLength, 1.0, 2 ); // prawa szyna za iglicą - SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, rpts2, nnumPts, fTexLength ); // lewa szyna normalnie cała + SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 ); // prawa iglica + SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, origin, rpts1, nnumPts, fTexLength, 1.0, 2 ); // prawa szyna za iglicą + SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, origin, rpts2, nnumPts, fTexLength ); // lewa szyna normalnie cała } if( TextureID2 ) { GfxRenderer.Bind( TextureID2 ); - SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, rpts1, nnumPts, fTexLength ); // prawa szyna normalna cała - SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 ); // lewa iglica - SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, rpts2, nnumPts, fTexLength, 1.0, 2 ); // lewa szyna za iglicą + SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, origin, rpts1, nnumPts, fTexLength ); // prawa szyna normalna cała + SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 ); // lewa iglica + SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, origin, rpts2, nnumPts, fTexLength, 1.0, 2 ); // lewa szyna za iglicą } } else { // lewa kiedyś działała lepiej niż prawa if( TextureID1 ) { GfxRenderer.Bind( TextureID1 ); - SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, rpts1, nnumPts, fTexLength ); // prawa szyna normalna cała - SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 ); // lewa iglica - SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, rpts2, nnumPts, fTexLength, 1.0, 2 ); // lewa szyna za iglicą + SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, origin, rpts1, nnumPts, fTexLength ); // prawa szyna normalna cała + SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 ); // lewa iglica + SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, origin, rpts2, nnumPts, fTexLength, 1.0, 2 ); // lewa szyna za iglicą } if( TextureID2 ) { // nie wiadomo, czy OpenGL to optymalizuje GfxRenderer.Bind( TextureID2 ); - SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 ); // prawa iglica - SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, rpts1, nnumPts, fTexLength, 1.0, 2 ); // prawa szyna za iglicą - SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, rpts2, nnumPts, fTexLength ); // lewa szyna normalnie cała + SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 ); // prawa iglica + SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, origin, rpts1, nnumPts, fTexLength, 1.0, 2 ); // prawa szyna za iglicą + SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, origin, rpts2, nnumPts, fTexLength ); // lewa szyna normalnie cała } } } @@ -1315,7 +1318,7 @@ void TTrack::Compile(GLuint tex) { // tworzenie trójkątów nawierzchni szosy if (!tex) GfxRenderer.Bind( TextureID1 ); - Segment->RenderLoft( immediate, bpts1, iTrapezoid ? -2 : 2, fTexLength); + Segment->RenderLoft( immediate, origin, bpts1, iTrapezoid ? -2 : 2, fTexLength); } if (TextureID2) if (tex ? TextureID2 == tex : true) // jeśli pasuje do grupy (tex) @@ -1399,16 +1402,16 @@ void TTrack::Compile(GLuint tex) { // pobocza do trapezowatej nawierzchni - dodatkowe punkty z drugiej strony // odcinka if ((fTexHeight1 >= 0.0) ? true : (slop != 0.0)) - Segment->RenderLoft( immediate, rpts1, -3, fTexLength); // tylko jeśli jest z prawej + Segment->RenderLoft( immediate, origin, rpts1, -3, fTexLength); // tylko jeśli jest z prawej if ((fTexHeight1 >= 0.0) ? true : (side != 0.0)) - Segment->RenderLoft( immediate, rpts2, -3, fTexLength); // tylko jeśli jest z lewej + Segment->RenderLoft( immediate, origin, rpts2, -3, fTexLength); // tylko jeśli jest z lewej } else { // pobocza zwykłe, brak przechyłki if ((fTexHeight1 >= 0.0) ? true : (slop != 0.0)) - Segment->RenderLoft( immediate, rpts1, 3, fTexLength); + Segment->RenderLoft( immediate, origin, rpts1, 3, fTexLength); if ((fTexHeight1 >= 0.0) ? true : (side != 0.0)) - Segment->RenderLoft( immediate, rpts2, 3, fTexLength); + Segment->RenderLoft( immediate, origin, rpts2, 3, fTexLength); } } break; @@ -1551,19 +1554,19 @@ void TTrack::Compile(GLuint tex) if (SwitchExtension->iRoads == 4) { // pobocza do trapezowatej nawierzchni - dodatkowe punkty z drugiej strony odcinka if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) { - SwitchExtension->Segments[ 2 ]->RenderLoft( immediate, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); - SwitchExtension->Segments[ 3 ]->RenderLoft( immediate, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); - SwitchExtension->Segments[ 4 ]->RenderLoft( immediate, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); - SwitchExtension->Segments[ 5 ]->RenderLoft( immediate, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); + SwitchExtension->Segments[ 2 ]->RenderLoft( immediate, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); + SwitchExtension->Segments[ 3 ]->RenderLoft( immediate, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); + SwitchExtension->Segments[ 4 ]->RenderLoft( immediate, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); + SwitchExtension->Segments[ 5 ]->RenderLoft( immediate, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); } } else // to będzie ewentualnie dla prostego na skrzyżowaniu trzech dróg { // punkt 3 pokrywa się z punktem 1, jak w zwrotnicy; połączenie 1->2 nie musi być prostoliniowe if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) { - SwitchExtension->Segments[ 2 ]->RenderLoft( immediate, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); // z P2 do P4 - SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); // z P4 do P3=P1 (odwrócony) - SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); // z P1 do P2 + SwitchExtension->Segments[ 2 ]->RenderLoft( immediate, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P2 do P4 + SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P4 do P3=P1 (odwrócony) + SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P1 do P2 } } } @@ -1628,7 +1631,7 @@ void TTrack::Compile(GLuint tex) { if (!tex) GfxRenderer.Bind( TextureID1 ); - Segment->RenderLoft( immediate, bpts1, numPts, fTexLength); + Segment->RenderLoft( immediate, origin, bpts1, numPts, fTexLength); } if (TextureID2) if (tex ? TextureID2 == tex : true) // jeśli pasuje do grupy (tex) @@ -1640,8 +1643,8 @@ void TTrack::Compile(GLuint tex) vector6(-rozp, -fTexHeight1, 0.0)}; // Ra: po kiego 0.1? if (!tex) GfxRenderer.Bind( TextureID2 ); // brzeg rzeki - Segment->RenderLoft( immediate, rpts1, 3, fTexLength); - Segment->RenderLoft( immediate, rpts2, 3, fTexLength); + Segment->RenderLoft( immediate, origin, rpts1, 3, fTexLength ); + Segment->RenderLoft( immediate, origin, rpts2, 3, fTexLength ); } break; } @@ -1858,6 +1861,9 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons hypot2 = hypot1; normal2 = normal1; } + + auto const origin = pMyNode->m_rootposition; + double roll1, roll2; switch (iCategoryFlag & 15) { @@ -1959,12 +1965,12 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons bpts1[3] = vector6(-rozp, -fTexHeight1 - 0.18, 0.5 + map12, -normal1.x, -normal1.y, 0.0); // prawy skos } } - Segment->RenderLoft(Vert, bpts1, iTrapezoid ? -4 : 4, fTexLength); + Segment->RenderLoft(Vert, origin, bpts1, iTrapezoid ? -4 : 4, fTexLength); } if (TextureID1) { // szyny - generujemy dwie, najwyżej rysować się będzie jedną - Segment->RenderLoft(Vert, rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength); - Segment->RenderLoft(Vert, rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength); + Segment->RenderLoft(Vert, origin, rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength); + Segment->RenderLoft(Vert, origin, rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength); } break; case tt_Switch: // dla zwrotnicy dwa razy szyny @@ -1989,32 +1995,32 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons if (SwitchExtension->RightSwitch) { // nowa wersja z SPKS, ale odwrotnie lewa/prawa if( TextureID1 ) { - SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, rpts2, nnumPts, fTexLength ); - SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, rpts1, nnumPts, fTexLength, 1.0, 2 ); + SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, origin, rpts2, nnumPts, fTexLength ); + SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, origin, rpts1, nnumPts, fTexLength, 1.0, 2 ); SwitchExtension->iLeftVBO = Vert - Start; // indeks lewej iglicy - SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 ); + SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 ); } if( TextureID2 ) { SwitchExtension->iRightVBO = Vert - Start; // indeks prawej iglicy - SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 ); - SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, rpts2, nnumPts, fTexLength, 1.0, 2 ); - SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, rpts1, nnumPts, fTexLength ); + SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 ); + SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, origin, rpts2, nnumPts, fTexLength, 1.0, 2 ); + SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, origin, rpts1, nnumPts, fTexLength ); } } else { // lewa działa lepiej niż prawa if( TextureID1 ) { - SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, rpts1, nnumPts, fTexLength ); // lewa szyna normalna cała - SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, rpts2, nnumPts, fTexLength, 1.0, 2 ); // prawa szyna za iglicą + SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, origin, rpts1, nnumPts, fTexLength ); // lewa szyna normalna cała + SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, origin, rpts2, nnumPts, fTexLength, 1.0, 2 ); // prawa szyna za iglicą SwitchExtension->iLeftVBO = Vert - Start; // indeks lewej iglicy - SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 ); // prawa iglica + SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 ); // prawa iglica } if( TextureID2 ) { SwitchExtension->iRightVBO = Vert - Start; // indeks prawej iglicy - SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 ); // lewa iglica - SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, rpts1, nnumPts, fTexLength, 1.0, 2 ); // lewa szyna za iglicą - SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, rpts2, nnumPts, fTexLength ); // prawa szyna normalnie cała + SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 ); // lewa iglica + SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, origin, rpts1, nnumPts, fTexLength, 1.0, 2 ); // lewa szyna za iglicą + SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, origin, rpts2, nnumPts, fTexLength ); // prawa szyna normalnie cała } } } @@ -2049,7 +2055,7 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons } if (TextureID1) // jeśli podana była tekstura, generujemy trójkąty { // tworzenie trójkątów nawierzchni szosy - Segment->RenderLoft(Vert, bpts1, iTrapezoid ? -2 : 2, fTexLength); + Segment->RenderLoft(Vert, origin, bpts1, iTrapezoid ? -2 : 2, fTexLength); } if (TextureID2) { // pobocze drogi - poziome przy przechyłce (a może krawężnik i chodnik zrobić jak w Midtown Madness 2?) @@ -2130,18 +2136,18 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons { // pobocza do trapezowatej nawierzchni - dodatkowe punkty z drugiej strony // odcinka if( ( fTexHeight1 >= 0.0 ) || ( slop != 0.0 ) ) { - Segment->RenderLoft( Vert, rpts1, -3, fTexLength ); // tylko jeśli jest z prawej + Segment->RenderLoft( Vert, origin, rpts1, -3, fTexLength ); // tylko jeśli jest z prawej } if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) { - Segment->RenderLoft( Vert, rpts2, -3, fTexLength ); // tylko jeśli jest z lewej + Segment->RenderLoft( Vert, origin, rpts2, -3, fTexLength ); // tylko jeśli jest z lewej } } else { // pobocza zwykłe, brak przechyłki if( ( fTexHeight1 >= 0.0 ) || ( slop != 0.0 ) ) { - Segment->RenderLoft( Vert, rpts1, 3, fTexLength ); + Segment->RenderLoft( Vert, origin, rpts1, 3, fTexLength ); } if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) { - Segment->RenderLoft( Vert, rpts2, 3, fTexLength ); + Segment->RenderLoft( Vert, origin, rpts2, 3, fTexLength ); } } } @@ -2266,18 +2272,18 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons if (SwitchExtension->iRoads == 4) { // pobocza do trapezowatej nawierzchni - dodatkowe punkty z drugiej strony odcinka if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) { - SwitchExtension->Segments[ 2 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); - SwitchExtension->Segments[ 3 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); - SwitchExtension->Segments[ 4 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); - SwitchExtension->Segments[ 5 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); + SwitchExtension->Segments[ 2 ]->RenderLoft( Vert, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); + SwitchExtension->Segments[ 3 ]->RenderLoft( Vert, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); + SwitchExtension->Segments[ 4 ]->RenderLoft( Vert, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); + SwitchExtension->Segments[ 5 ]->RenderLoft( Vert, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); } } else { // punkt 3 pokrywa się z punktem 1, jak w zwrotnicy; połączenie 1->2 nie musi być prostoliniowe if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) { - SwitchExtension->Segments[ 2 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); // z P2 do P4 - SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); // z P4 do P3=P1 (odwrócony) - SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); // z P1 do P2 + SwitchExtension->Segments[ 2 ]->RenderLoft( Vert, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P2 do P4 + SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P4 do P3=P1 (odwrócony) + SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P1 do P2 } } } @@ -2297,17 +2303,17 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons Vert->nz = 0.0; Vert->u = 0.5; Vert->v = 0.5; - Vert->x = oxz.x; - Vert->y = oxz.y; - Vert->z = oxz.z; + Vert->x = oxz.x - origin.x; + Vert->y = oxz.y - origin.y; + Vert->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; // mapowanie we współrzędnych scenerii - u = ( SwitchExtension->vPoints[ 0 ].x - oxz.x ) / fTexLength; - v = ( SwitchExtension->vPoints[ 0 ].z - oxz.z ) / ( fTexRatio1 * fTexLength ); + 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; @@ -2321,8 +2327,8 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons Vert->ny = 1.0; Vert->nz = 0.0; // mapowanie we współrzędnych scenerii - u = (SwitchExtension->vPoints[i].x - oxz.x) / fTexLength; - v = (SwitchExtension->vPoints[i].z - oxz.z) / (fTexRatio1 * fTexLength); + 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; @@ -2368,7 +2374,7 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons } if (TextureID1) // jeśli podana była tekstura, generujemy trójkąty { // tworzenie trójkątów nawierzchni szosy - Segment->RenderLoft(Vert, bpts1, iTrapezoid ? -2 : 2, fTexLength); + Segment->RenderLoft(Vert, origin, bpts1, iTrapezoid ? -2 : 2, fTexLength); } if (TextureID2) { // pobocze drogi - poziome przy przechyłce (a może krawężnik i chodnik zrobić jak w @@ -2390,13 +2396,13 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons rpts2[3] = vector6(bpts1[3].x, bpts1[3].y, 1.0); rpts2[4] = vector6(bpts1[3].x - side2, bpts1[3].y, 0.5); rpts2[5] = vector6(-rozp2, -fTexHeight2, 0.0); // prawy brzeg prawego pobocza - Segment->RenderLoft(Vert, rpts1, -3, fTexLength); - Segment->RenderLoft(Vert, rpts2, -3, fTexLength); + Segment->RenderLoft(Vert, origin, rpts1, -3, fTexLength); + Segment->RenderLoft(Vert, origin, rpts2, -3, fTexLength); } else { // pobocza zwykłe, brak przechyłki - Segment->RenderLoft(Vert, rpts1, 3, fTexLength); - Segment->RenderLoft(Vert, rpts2, 3, fTexLength); + Segment->RenderLoft(Vert, origin, rpts1, 3, fTexLength); + Segment->RenderLoft(Vert, origin, rpts2, 3, fTexLength); } } } @@ -2884,13 +2890,14 @@ TTrack * TTrack::RaAnimate(GLuint const Vertexbuffer) bladesbuffer.data() ); */ auto bladevertices = bladesbuffer.data(); + auto const origin = pMyNode->m_rootposition; if( SwitchExtension->RightSwitch ) { // nowa wersja z SPKS, ale odwrotnie lewa/prawa - SwitchExtension->Segments[ 0 ]->RenderLoft( bladevertices, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 /*, true*/ ); - SwitchExtension->Segments[ 1 ]->RenderLoft( bladevertices, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 /*, true*/ ); + 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*/ ); } else { - SwitchExtension->Segments[ 0 ]->RenderLoft( bladevertices, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 /*, true*/ ); // prawa iglica - SwitchExtension->Segments[ 1 ]->RenderLoft( bladevertices, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 /*, true*/ ); // lewa iglica + SwitchExtension->Segments[ 0 ]->RenderLoft( bladevertices, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 /*, true*/ ); // prawa iglica + SwitchExtension->Segments[ 1 ]->RenderLoft( bladevertices, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 /*, true*/ ); // lewa iglica } // push back updated geometry ::glBufferSubData( diff --git a/Traction.cpp b/Traction.cpp index 8324854a..6cf2842a 100644 --- a/Traction.cpp +++ b/Traction.cpp @@ -324,7 +324,7 @@ int TTraction::RaArrayPrepare() return iLines; }; -int TTraction::RaArrayFill(CVertNormTex *Vert) +int TTraction::RaArrayFill(CVertNormTex *Vert, Math3D::vector3 const &Origin) { // wypełnianie tablic VBO int debugvertexcount{ 0 }; @@ -332,14 +332,14 @@ int TTraction::RaArrayFill(CVertNormTex *Vert) if (Wires == 2) WireOffset = 0; // jezdny - Vert->x = pPoint1.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset; - Vert->y = pPoint1.y; - Vert->z = pPoint1.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset; + Vert->x = pPoint1.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x; + Vert->y = pPoint1.y - Origin.y; + Vert->z = pPoint1.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z; ++Vert; ++debugvertexcount; - Vert->x = pPoint2.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset; - Vert->y = pPoint2.y; - Vert->z = pPoint2.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset; + Vert->x = pPoint2.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x; + Vert->y = pPoint2.y - Origin.y; + Vert->z = pPoint2.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z; ++Vert; ++debugvertexcount; // Nie wiem co 'Marcin @@ -355,9 +355,9 @@ int TTraction::RaArrayFill(CVertNormTex *Vert) // Przewod nosny 'Marcin if (Wires > 1) { // lina nośna w kawałkach - Vert->x = pPoint3.x; - Vert->y = pPoint3.y; - Vert->z = pPoint3.z; + Vert->x = pPoint3.x - Origin.x; + Vert->y = pPoint3.y - Origin.y; + Vert->z = pPoint3.z - Origin.z; ++Vert; ++debugvertexcount; for (int i = 0; i < iNumSections - 1; ++i) @@ -367,31 +367,31 @@ int TTraction::RaArrayFill(CVertNormTex *Vert) if( ( Wires < 4 ) || ( ( i != 0 ) && ( i != iNumSections - 2 ) ) ) { - Vert->x = pt3.x; - Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference; - Vert->z = pt3.z; + Vert->x = pt3.x - Origin.x; + Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - Origin.y; + Vert->z = pt3.z - Origin.z; ++Vert; ++debugvertexcount; } f += step; } - Vert->x = pPoint4.x; - Vert->y = pPoint4.y; - Vert->z = pPoint4.z; + Vert->x = pPoint4.x - Origin.x; + Vert->y = pPoint4.y - Origin.y; + Vert->z = pPoint4.z - Origin.z; ++Vert; ++debugvertexcount; } // Drugi przewod jezdny 'Winger if (Wires > 2) { - Vert->x = pPoint1.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset; - Vert->y = pPoint1.y; - Vert->z = pPoint1.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset; + Vert->x = pPoint1.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset - Origin.x; + Vert->y = pPoint1.y - Origin.y; + Vert->z = pPoint1.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset - Origin.z; ++Vert; ++debugvertexcount; - Vert->x = pPoint2.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset; - Vert->y = pPoint2.y; - Vert->z = pPoint2.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset; + Vert->x = pPoint2.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset - Origin.x; + Vert->y = pPoint2.y - Origin.y; + Vert->z = pPoint2.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset - Origin.z; ++Vert; ++debugvertexcount; } @@ -399,28 +399,29 @@ int TTraction::RaArrayFill(CVertNormTex *Vert) f = step; if( Wires == 4 ) { - Vert->x = pPoint3.x; - Vert->y = pPoint3.y - 0.65f * fHeightDifference; - Vert->z = pPoint3.z; + Vert->x = pPoint3.x - Origin.x; + Vert->y = pPoint3.y - 0.65f * fHeightDifference - Origin.y; + Vert->z = pPoint3.z - Origin.z; ++Vert; ++debugvertexcount; for( int i = 0; i < iNumSections - 1; ++i ) { pt3 = pPoint3 + v1 * f; t = ( 1 - std::fabs( f - mid ) * 2 ); - Vert->x = pt3.x; + Vert->x = pt3.x - Origin.x; Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - ( ( ( i == 0 ) || ( i == iNumSections - 2 ) ) ? 0.25f * fHeightDifference : - 0.05 ); - Vert->z = pt3.z; + 0.05 ) + - Origin.y; + Vert->z = pt3.z - Origin.z; ++Vert; ++debugvertexcount; f += step; } - Vert->x = pPoint4.x; - Vert->y = pPoint4.y - 0.65f * fHeightDifference; - Vert->z = pPoint4.z; + Vert->x = pPoint4.x - Origin.x; + Vert->y = pPoint4.y - 0.65f * fHeightDifference - Origin.y; + Vert->z = pPoint4.z - Origin.z; ++Vert; ++debugvertexcount; } @@ -439,40 +440,40 @@ int TTraction::RaArrayFill(CVertNormTex *Vert) t = (1 - std::fabs(f - mid) * 2); if( ( i % 2 ) == 0 ) { - Vert->x = pt3.x; - Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - ( ( i == 0 ) || ( i == iNumSections - 2 ) ? flo : flo1 ); - Vert->z = pt3.z; + Vert->x = pt3.x - Origin.x; + Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - ( ( i == 0 ) || ( i == iNumSections - 2 ) ? flo : flo1 ) - Origin.y; + Vert->z = pt3.z - Origin.z; ++Vert; ++debugvertexcount; - Vert->x = pt4.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset; - Vert->y = pt4.y; - Vert->z = pt4.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset; + Vert->x = pt4.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x; + Vert->y = pt4.y - Origin.y; + Vert->z = pt4.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z; ++Vert; ++debugvertexcount; } else { - Vert->x = pt3.x; - Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - ( ( i == 0 ) || ( i == iNumSections - 2 ) ? flo : flo1 ); - Vert->z = pt3.z; + Vert->x = pt3.x - Origin.x; + Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - ( ( i == 0 ) || ( i == iNumSections - 2 ) ? flo : flo1 ) - Origin.y; + Vert->z = pt3.z - Origin.z; ++Vert; ++debugvertexcount; - Vert->x = pt4.x + ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset; - Vert->y = pt4.y; - Vert->z = pt4.z + ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset; + Vert->x = pt4.x + ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x; + Vert->y = pt4.y - Origin.y; + Vert->z = pt4.z + ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z; ++Vert; ++debugvertexcount; } if( ( ( Wires == 4 ) && ( ( i == 1 ) || ( i == iNumSections - 3 ) ) ) ) { - Vert->x = pt3.x; - Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - 0.05; - Vert->z = pt3.z; + Vert->x = pt3.x - Origin.x; + Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - 0.05 - Origin.y; + Vert->z = pt3.z - Origin.z; ++Vert; ++debugvertexcount; - Vert->x = pt3.x; - Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference; - Vert->z = pt3.z; + Vert->x = pt3.x - Origin.x; + Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - Origin.y; + Vert->z = pt3.z - Origin.z; ++Vert; ++debugvertexcount; } diff --git a/Traction.h b/Traction.h index e276bf59..5a68c359 100644 --- a/Traction.h +++ b/Traction.h @@ -68,7 +68,7 @@ class TTraction // virtual void SelectedRender(); void RenderDL(float mgn); int RaArrayPrepare(); - int RaArrayFill(CVertNormTex *Vert); + int RaArrayFill( CVertNormTex *Vert, Math3D::vector3 const &Origin ); void RenderVBO(float mgn, int iPtr); int TestPoint(Math3D::vector3 *Point); void Connect(int my, TTraction *with, int to); diff --git a/World.cpp b/World.cpp index d7fa9bae..dc3c4968 100644 --- a/World.cpp +++ b/World.cpp @@ -1276,6 +1276,8 @@ TWorld::Render_Cab() { return; } + ::glEnable( GL_LIGHTING ); // po renderowaniu drutów może być to wyłączone. TODO: have the wires render take care of its own shit +/* glPushMatrix(); vector3 pos = dynamic->GetPosition(); // wszpółrzędne pojazdu z kabiną // glTranslatef(pos.x,pos.y,pos.z); //przesunięcie o wektor (tak było i trzęsło) @@ -1284,7 +1286,11 @@ TWorld::Render_Cab() { glLoadIdentity(); // zacząć od macierzy jedynkowej Camera.SetCabMatrix( pos ); // widok z kamery po przesunięciu glMultMatrixd( dynamic->mMatrix.getArray() ); // ta macierz nie ma przesunięcia - glEnable( GL_LIGHTING ); // po renderowaniu drutów może być to wyłączone. TODO: have the wires render take care of its own shit +*/ + ::glPushMatrix(); + auto const originoffset = dynamic->GetPosition() - Global::pCameraPosition; + ::glTranslated( originoffset.x, originoffset.y, originoffset.z ); + ::glMultMatrixd( dynamic->mMatrix.getArray() ); if( dynamic->mdKabina ) // bo mogła zniknąć przy przechodzeniu do innego pojazdu { diff --git a/frustum.h b/frustum.h index 19febbe3..360f8a5a 100644 --- a/frustum.h +++ b/frustum.h @@ -27,6 +27,9 @@ public: calculate(glm::mat4 const &Projection, glm::mat4 const &Modelview); // returns true if specified point is inside of the frustum inline + bool + point_inside( glm::vec3 const &Point ) const { return point_inside( Point.x, Point.y, Point.z ); } + inline bool point_inside( float3 const &Point ) const { return point_inside( Point.x, Point.y, Point.z ); } inline @@ -36,6 +39,9 @@ public: point_inside( float const X, float const Y, float const Z ) const; // tests if the sphere is in frustum, returns the distance between origin and sphere centre inline + float + sphere_inside( glm::vec3 const &Center, float const Radius ) const { return sphere_inside( Center.x, Center.y, Center.z, Radius ); } + inline float sphere_inside( float3 const &Center, float const Radius ) const { return sphere_inside( Center.x, Center.y, Center.z, Radius ); } inline @@ -45,6 +51,9 @@ public: sphere_inside( float const X, float const Y, float const Z, float const Radius ) const; // returns true if specified cube is inside of the frustum. Size = half of the length inline + bool + cube_inside( glm::vec3 const &Center, float const Size ) const { return cube_inside( Center.x, Center.y, Center.z, Size ); } + inline bool cube_inside( float3 const &Center, float const Size ) const { return cube_inside( Center.x, Center.y, Center.z, Size ); } inline diff --git a/renderer.cpp b/renderer.cpp index 2fe2ede1..0403e303 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -142,9 +142,16 @@ opengl_renderer::Render() { ::glLoadIdentity(); if( World.InitPerformed() ) { - +/* World.Camera.SetMatrix(); m_camera.update_frustum(); +*/ + glm::dmat4 worldcamera; + World.Camera.SetMatrix( worldcamera ); + m_camera.update_frustum( OpenGLMatrices.data( GL_PROJECTION ), worldcamera ); + // frustum tests are performed in 'world space' but after we set up frustum + // we no longer need camera translation, only rotation + ::glMultMatrixd( glm::value_ptr( glm::dmat4( glm::dmat3( worldcamera )))); Render( &World.Environment ); Render( &World.Ground ); @@ -178,11 +185,12 @@ opengl_renderer::Render( world_environment *Environment ) { /* ::glTranslatef( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z ); */ +/* glm::mat4 worldcamera; World.Camera.SetMatrix( worldcamera ); glLoadIdentity(); glMultMatrixf( glm::value_ptr( glm::mat4( glm::mat3( worldcamera ) ) ) ); - +*/ // setup fog if( Global::fFogEnd > 0 ) { // fog setup @@ -294,12 +302,16 @@ opengl_renderer::Render( world_environment *Environment ) { bool opengl_renderer::Render( TGround *Ground ) { -/* - glDisable( GL_BLEND ); - glAlphaFunc( GL_GREATER, 0.50f ); // im mniejsza wartość, tym większa ramka, domyślnie 0.1f - glEnable( GL_LIGHTING ); - glColor3f( 1.0f, 1.0f, 1.0f ); + ::glEnable( GL_LIGHTING ); + ::glDisable( GL_BLEND ); + ::glAlphaFunc( GL_GREATER, 0.50f ); // im mniejsza wartość, tym większa ramka, domyślnie 0.1f + ::glColor3f( 1.0f, 1.0f, 1.0f ); + + ++TGroundRect::iFrameNumber; // zwięszenie licznika ramek (do usuwniania nadanimacji) + + Update_Lights( Ground->m_lights ); +/* glm::vec3 const cameraposition( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z ); int const camerax = static_cast( std::floor( cameraposition.x / 1000.0f ) + iNumRects / 2 ); int const cameraz = static_cast( std::floor( cameraposition.z / 1000.0f ) + iNumRects / 2 ); @@ -317,15 +329,6 @@ opengl_renderer::Render( TGround *Ground ) { } } */ - ::glEnable( GL_LIGHTING ); - ::glDisable( GL_BLEND ); - ::glAlphaFunc( GL_GREATER, 0.50f ); // im mniejsza wartość, tym większa ramka, domyślnie 0.1f - ::glColor3f( 1.0f, 1.0f, 1.0f ); - - ++TGroundRect::iFrameNumber; // zwięszenie licznika ramek (do usuwniania nadanimacji) - - Update_Lights( Ground->m_lights ); - Ground->CameraDirection.x = std::sin( Global::pCameraRotation ); // wektor kierunkowy Ground->CameraDirection.z = std::cos( Global::pCameraRotation ); TGroundNode *node; @@ -354,6 +357,16 @@ opengl_renderer::Render( TGround *Ground ) { } } // renderowanie progresywne - zależne od FPS oraz kierunku patrzenia + // pre-calculate camera view span + double const fieldofviewcosine = + std::cos( + std::max( + // vertical... + Global::FieldOfView / Global::ZoomFactor, + // ...or horizontal, whichever is bigger + Global::FieldOfView / Global::ZoomFactor + * std::max( 1.0f, (float)Global::ScreenWidth ) / std::max( 1.0f, (float)Global::ScreenHeight ) ) ); + Ground->iRendered = 0; // ilość renderowanych sektorów Math3D::vector3 direction; for( k = 0; k < Global::iSegmentsRendered; ++k ) // sektory w kolejności odległości @@ -369,10 +382,16 @@ opengl_renderer::Render( TGround *Ground ) { if( Math3D::LengthSquared3( direction ) > 5 ) // te blisko są zawsze wyświetlane { direction = Math3D::SafeNormalize( direction ); // normalizacja - if( Ground->CameraDirection.x * direction.x + Ground->CameraDirection.z * direction.z < 0.55 ) + if( Ground->CameraDirection.x * direction.x + Ground->CameraDirection.z * direction.z < 0.5 ) continue; // pomijanie sektorów poza kątem patrzenia } // kwadrat kilometrowy nie zawsze, bo szkoda FPS + // TODO: unify all math objects + ::glPushMatrix(); + auto const &cellorigin = Ground->Rects[ ( i + c ) / iNumSubRects ][ ( j + r ) / iNumSubRects ].m_area.center; + auto const originoffset = Math3D::vector3( cellorigin.x, cellorigin.y, cellorigin.z ) - Global::pCameraPosition; + ::glTranslated( originoffset.x, originoffset.y, originoffset.z ); + if( Global::bUseVBO ) { // vbo render path Ground->Rects[ ( i + c ) / iNumSubRects ][ ( j + r ) / iNumSubRects ].RenderVBO(); @@ -381,6 +400,8 @@ opengl_renderer::Render( TGround *Ground ) { // display list render path Ground->Rects[ ( i + c ) / iNumSubRects ][ ( j + r ) / iNumSubRects ].RenderDL(); } + ::glPopMatrix(); + if( ( tmp = Ground->FastGetSubRect( i + c, j + r ) ) != nullptr ) { if( tmp->iNodeCount ) { // o ile są jakieś obiekty, bo po co puste sektory przelatywać @@ -389,16 +410,15 @@ 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 ) { Global::pTerrainCompact->TerrainRenderVBO( TGroundRect::iFrameNumber ); } } - // renderowanie nieprzezroczystych for( i = 0; i < Ground->iRendered; ++i ) { + if( Global::bUseVBO ) { // vbo render path Ground->pRendered[ i ]->RenderVBO(); @@ -408,10 +428,8 @@ opengl_renderer::Render( TGround *Ground ) { Ground->pRendered[ i ]->RenderDL(); } } - // regular render takes care of all solid geometry present in the scene, thus we can launch alpha parts render here return Render_Alpha( Ground ); - } bool @@ -436,22 +454,30 @@ opengl_renderer::Render( TGroundNode *Node ) { switch (Node->iType) { case TP_TRACK: { + + if( Global::bUseVBO && ( Node->iNumVerts <= 0 ) ) { + return false; + } + // setup + ::glPushMatrix(); + auto const originoffset = Node->m_rootposition - Global::pCameraPosition; + ::glTranslated( originoffset.x, originoffset.y, originoffset.z ); + // TODO: unify the render code after generic buffers are in place if( Global::bUseVBO ) { - if( Node->iNumVerts ) { - Node->pTrack->RaRenderVBO( Node->iVboPtr ); - } - else { - return false; - } + // vbo render path + Node->pTrack->RaRenderVBO( Node->iVboPtr ); } else { + // display list render path Node->pTrack->Render(); } + // post-render cleanup + ::glPopMatrix(); return true; } case TP_MODEL: { - Node->Model->Render( &Node->pCenter ); + Node->Model->Render( Node->pCenter - Global::pCameraPosition ); return true; } case TP_MEMCELL: { @@ -480,6 +506,9 @@ opengl_renderer::Render( TGroundNode *Node ) { // wszelkie linie są rysowane na samym końcu if( Node->iNumPts ) { // setup + ::glPushMatrix(); + auto const originoffset = Node->m_rootposition - Global::pCameraPosition; + ::glTranslated( originoffset.x, originoffset.y, originoffset.z ); // w zaleznosci od koloru swiatla ::glColor4ub( static_cast( std::floor( Node->Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ] ) ), @@ -497,6 +526,9 @@ opengl_renderer::Render( TGroundNode *Node ) { else { ::glCallList( Node->DisplayListID ); } + + // post-render cleanup + ::glPopMatrix(); return true; } else { @@ -505,7 +537,17 @@ opengl_renderer::Render( TGroundNode *Node ) { } else { // GL_TRIANGLE etc + if( ( Global::bUseVBO ? + Node->iVboPtr < 0 : + Node->DisplayListID == 0 ) ) { + return false; + } + // setup + ::glPushMatrix(); + auto const originoffset = Node->m_rootposition - Global::pCameraPosition; + ::glTranslated( originoffset.x, originoffset.y, originoffset.z ); + ::glColor3ub( static_cast( Node->Diffuse[ 0 ] ), static_cast( Node->Diffuse[ 1 ] ), @@ -517,22 +559,16 @@ opengl_renderer::Render( TGroundNode *Node ) { // TODO: unify the render code after generic buffers are in place if( Global::bUseVBO ) { // vbo render path - if( Node->iVboPtr >= 0 ) { - ::glDrawArrays( Node->iType, Node->iVboPtr, Node->iNumVerts ); - } - else { - return false; - } + ::glDrawArrays( Node->iType, Node->iVboPtr, Node->iNumVerts ); } else { // display list render path - if( Node->DisplayListID != 0 ) { - ::glCallList( Node->DisplayListID ); - } - else { - return false; - } + ::glCallList( Node->DisplayListID ); } + + // post-render cleanup + ::glPopMatrix(); + return true; } } @@ -550,11 +586,11 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) { // setup TSubModel::iInstance = ( size_t )this; //żeby nie robić cudzych animacji - double squaredistance = SquareMagnitude( ( Global::pCameraPosition - Dynamic->vPosition ) / Global::ZoomFactor ); + auto const originoffset = Dynamic->vPosition - Global::pCameraPosition; + double const squaredistance = SquareMagnitude( originoffset / Global::ZoomFactor ); Dynamic->ABuLittleUpdate( squaredistance ); // ustawianie zmiennych submodeli dla wspólnego modelu - ::glPushMatrix(); - +/* if( Dynamic == Global::pUserDynamic ) { //specjalne ustawienie, aby nie trzęsło //tu trzeba by ustawić animacje na modelu zewnętrznym @@ -563,7 +599,8 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) { } else ::glTranslated( Dynamic->vPosition.x, Dynamic->vPosition.y, Dynamic->vPosition.z ); // standardowe przesunięcie względem początku scenerii - +*/ + ::glTranslated( originoffset.x, originoffset.y, originoffset.z ); ::glMultMatrixd( Dynamic->mMatrix.getArray() ); if( Dynamic->fShade > 0.0f ) { @@ -666,7 +703,7 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, Math3D: if( Angle.z != 0.0 ) ::glRotated( Angle.z, 0.0, 0.0, 1.0 ); - auto const result = Render( Model, Material, SquareMagnitude( Position - Global::GetCameraPosition() ) ); + auto const result = Render( Model, Material, SquareMagnitude( Position / Global::ZoomFactor ) ); // position is effectively camera offset ::glPopMatrix(); @@ -932,12 +969,19 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) { case TP_TRACTION: { // TODO: unify the render code after generic buffers are in place if( Node->bVisible ) { + // setup + ::glPushMatrix(); + auto const originoffset = Node->m_rootposition - Global::pCameraPosition; + ::glTranslated( originoffset.x, originoffset.y, originoffset.z ); + // render if( Global::bUseVBO ) { Node->hvTraction->RenderVBO( distancesquared, Node->iVboPtr ); } else { Node->hvTraction->RenderDL( distancesquared ); } + // post-render cleanup + ::glPopMatrix(); return true; } else { @@ -945,7 +989,7 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) { } } case TP_MODEL: { - Node->Model->RenderAlpha( &Node->pCenter ); + Node->Model->RenderAlpha( Node->pCenter - Global::pCameraPosition ); return true; } } @@ -980,6 +1024,9 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) { // wszelkie linie są rysowane na samym końcu if( Node->iNumPts ) { // setup + ::glPushMatrix(); + auto const originoffset = Node->m_rootposition - Global::pCameraPosition; + ::glTranslated( originoffset.x, originoffset.y, originoffset.z ); // w zaleznosci od koloru swiatla ::glColor4ub( static_cast( std::floor( Node->Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ] ) ), @@ -997,12 +1044,18 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) { else { ::glCallList( Node->DisplayListID ); } + // post-render cleanup + ::glPopMatrix(); result = true; } } else { // GL_TRIANGLE etc // setup + ::glPushMatrix(); + auto const originoffset = Node->m_rootposition - Global::pCameraPosition; + ::glTranslated( originoffset.x, originoffset.y, originoffset.z ); + ::glColor3ub( static_cast( Node->Diffuse[ 0 ] ), static_cast( Node->Diffuse[ 1 ] ), @@ -1024,8 +1077,10 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) { ::glCallList( Node->DisplayListID ); result = true; } + // post-render cleanup + ::glPopMatrix(); } - // post-render cleanup + #ifdef _PROBLEND if( ( Node->PROBLEND ) ) // sprawdza, czy w nazwie nie ma @ //Q: 13122011 - Szociu: 27012012 { @@ -1049,17 +1104,19 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) { // setup TSubModel::iInstance = ( size_t )this; //żeby nie robić cudzych animacji - double squaredistance = SquareMagnitude( ( Global::pCameraPosition - Dynamic->vPosition ) / Global::ZoomFactor ); + auto const originoffset = Dynamic->vPosition - Global::pCameraPosition; + double const squaredistance = SquareMagnitude( originoffset / Global::ZoomFactor ); Dynamic->ABuLittleUpdate( squaredistance ); // ustawianie zmiennych submodeli dla wspólnego modelu - ::glPushMatrix(); +/* if( Dynamic == Global::pUserDynamic ) { // specjalne ustawienie, aby nie trzęsło ::glLoadIdentity(); // zacząć od macierzy jedynkowej Global::pCamera->SetCabMatrix( Dynamic->vPosition ); // specjalne ustawienie kamery } else ::glTranslated( Dynamic->vPosition.x, Dynamic->vPosition.y, Dynamic->vPosition.z ); // standardowe przesunięcie względem początku scenerii - +*/ + ::glTranslated( originoffset.x, originoffset.y, originoffset.z ); ::glMultMatrixd( Dynamic->mMatrix.getArray() ); if( Dynamic->fShade > 0.0f ) { @@ -1161,7 +1218,7 @@ opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, M if( Angle.z != 0.0 ) ::glRotated( Angle.z, 0.0, 0.0, 1.0 ); - auto const result = Render_Alpha( Model, Material, SquareMagnitude( Position - Global::GetCameraPosition() ) ); + auto const result = Render_Alpha( Model, Material, SquareMagnitude( Position / Global::ZoomFactor ) ); // position is effectively camera offset ::glPopMatrix(); @@ -1400,7 +1457,7 @@ opengl_renderer::Update_Lights( light_array const &Lights ) { continue; } // if the light passed tests so far, it's good enough - renderlight->set_position( scenelight.position ); + renderlight->set_position( scenelight.position - Global::pCameraPosition ); renderlight->direction = scenelight.direction; auto luminance = Global::fLuminance; // TODO: adjust this based on location, e.g. for tunnels diff --git a/renderer.h b/renderer.h index 65531612..1b478d3c 100644 --- a/renderer.h +++ b/renderer.h @@ -94,7 +94,7 @@ public: update_frustum() { m_frustum.calculate(); } inline void - update_frustum(glm::mat4 &Projection, glm::mat4 &Modelview) { m_frustum.calculate(Projection, Modelview); } + update_frustum(glm::mat4 const &Projection, glm::mat4 const &Modelview) { m_frustum.calculate(Projection, Modelview); } bool visible( bounding_area const &Area ) const; bool