From c38511978d80dffee342dc31083b5b7d2b161015 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Fri, 19 May 2017 20:07:23 +0200 Subject: [PATCH] build 170519. fixes for buffer overflows in segment.cpp --- Ground.cpp | 27 +++++++-- Segment.cpp | 152 ++++++++++++++++++++++++++++----------------------- Segment.h | 2 +- Track.cpp | 138 +++++++++++++++++++++++++++++++--------------- Track.h | 2 +- Traction.cpp | 22 +++++++- Traction.h | 2 +- version.h | 2 +- 8 files changed, 226 insertions(+), 121 deletions(-) diff --git a/Ground.cpp b/Ground.cpp index d1ed6969..087e76fb 100644 --- a/Ground.cpp +++ b/Ground.cpp @@ -787,6 +787,7 @@ void TSubRect::LoadNodes() return; // jeśli nie ma obiektów do wyświetlenia z VBO, to koniec if (Global::bUseVBO) { // tylko liczenie wierzchołów, gdy nie ma VBO + int debugvertexcount{ 0 }; MakeArray(m_nVertexCount); n = nRootNode; int i; @@ -808,7 +809,9 @@ void TSubRect::LoadNodes() m_pVNT[n->iVboPtr + i].nz = n->Vertices[i].Normal.z; m_pVNT[n->iVboPtr + i].u = n->Vertices[i].tu; m_pVNT[n->iVboPtr + i].v = n->Vertices[i].tv; + ++debugvertexcount; } + assert( debugvertexcount <= m_nVertexCount ); break; case GL_LINES: case GL_LINE_STRIP: @@ -819,23 +822,35 @@ void TSubRect::LoadNodes() m_pVNT[n->iVboPtr + i].y = n->Points[i].y; m_pVNT[n->iVboPtr + i].z = n->Points[i].z; // miejsce w tablicach normalnych i teksturowania się marnuje... + ++debugvertexcount; } + assert( debugvertexcount <= m_nVertexCount ); break; case TP_TRACK: - if (n->iNumVerts) // bo tory zabezpieczające są niewidoczne + if( n->iNumVerts ) { // bo tory zabezpieczające są niewidoczne #ifdef EU07_USE_OLD_VERTEXBUFFER - n->pTrack->RaArrayFill( m_pVNT + n->iVboPtr, m_pVNT ); + int const batch = n->pTrack->RaArrayFill( m_pVNT + n->iVboPtr, m_pVNT, std::min( n->iNumVerts, m_nVertexCount - n->iVboPtr ) ); #else - n->pTrack->RaArrayFill(m_pVNT.data() + n->iVboPtr, m_pVNT.data()); + int const batch = n->pTrack->RaArrayFill( m_pVNT.data() + n->iVboPtr, m_pVNT.data(), std::min( n->iNumVerts, m_nVertexCount - n->iVboPtr ) ); #endif + assert( batch == n->iNumVerts ); + assert( batch + n->iVboPtr <= m_nVertexCount ); + debugvertexcount += batch; + assert( debugvertexcount <= m_nVertexCount ); + } break; case TP_TRACTION: - if (n->iNumVerts) // druty mogą być niewidoczne...? + if( n->iNumVerts ) { // druty mogą być niewidoczne...? #ifdef EU07_USE_OLD_VERTEXBUFFER - n->hvTraction->RaArrayFill( m_pVNT + n->iVboPtr ); + int const batch = n->hvTraction->RaArrayFill( m_pVNT + n->iVboPtr ); #else - n->hvTraction->RaArrayFill(m_pVNT.data() + n->iVboPtr); + int const batch = n->hvTraction->RaArrayFill( m_pVNT.data() + n->iVboPtr ); #endif + assert( batch == n->iNumVerts ); + assert( batch + n->iVboPtr <= m_nVertexCount ); + debugvertexcount += batch; + assert( debugvertexcount <= m_nVertexCount ); + } break; } n = n->nNext2; // następny z sektora diff --git a/Segment.cpp b/Segment.cpp index 1455414b..75a8e335 100644 --- a/Segment.cpp +++ b/Segment.cpp @@ -116,26 +116,24 @@ bool TSegment::Init(vector3 &NewPoint1, vector3 NewCPointOut, vector3 NewCPointI // MessageBox(0,"Length<=0","TSegment::Init",MB_OK); return false; // zerowe nie mogą być } + + if( ( pOwner->eType == tt_Switch ) + && ( fStep * 3.0 > fLength ) ) { + // NOTE: a workaround for too short switches (less than 3 segments) messing up animation/generation of blades + fStep = fLength / 3.0; + } + fStoop = std::atan2((Point2.y - Point1.y), fLength); // pochylenie toru prostego, żeby nie liczyć wielokrotnie SafeDeleteArray(fTsBuffer); - if( ( bCurve ) && ( fStep > 0 ) ) { - if( fStep > 0 ) { // Ra: prosty dostanie podział, jak ma różną przechyłkę na końcach - double s = 0; - int i = 0; - iSegCount = static_cast( std::ceil( fLength / fStep )); // potrzebne do VBO - // fStep=fLength/(double)(iSegCount-1); //wyrównanie podziału - fTsBuffer = new double[ iSegCount + 1 ]; - fTsBuffer[ 0 ] = 0; /* TODO : fix fTsBuffer */ - while( s < fLength ) { - i++; - s += fStep; - if( s > fLength ) - s = fLength; - fTsBuffer[ i ] = GetTFromS( s ); - } - } + iSegCount = static_cast( std::ceil( fLength / fStep ) ); // potrzebne do VBO + fTsBuffer = new double[ iSegCount + 1 ]; + fTsBuffer[ 0 ] = 0.0; + for( int i = 1; i < iSegCount; ++i ) { + fTsBuffer[ i ] = GetTFromS( i * fStep ); } + fTsBuffer[ iSegCount ] = 1.0; + return true; } @@ -317,14 +315,16 @@ vector3 TSegment::FastGetPoint(double t) return (bCurve ? RaInterpolate(t) : ((1.0 - t) * Point1 + (t)*Point2)); } -void 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, const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale, int iSkip, int iEnd, double fOffsetX, bool Onlypositions, 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 // podany jest przekrój końcowy // podsypka toru jest robiona za pomocą 6 punktów, szyna 12, drogi i rzeki na 3+2+3 + int debugvertexcount{ 0 }; + if( !fTsBuffer ) - return; // prowizoryczne zabezpieczenie przed wysypem - ustalić faktyczną przyczynę + return debugvertexcount; // prowizoryczne zabezpieczenie przed wysypem - ustalić faktyczną przyczynę vector3 pos1, pos2, dir, parallel1, parallel2, pt, norm; double s, step, fOffset, tv1, tv2, t, fEnd; @@ -348,6 +348,9 @@ void TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, in fEnd = fLength * double( iEnd ) / double( iSegCount ); m2 = s / fEnd; jmm2 = 1.0 - m2; + + int const debugvertexlimit = std::abs( iNumShapePoints ) * 2 * ( iEnd - iSkip ); + while( i < iEnd ) { ++i; // kolejny punkt łamanej @@ -410,6 +413,7 @@ void TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, in } ++Output; } + ++debugvertexcount; } if( p ) // jeśli jest wskaźnik do tablicy if( *p ) @@ -447,6 +451,7 @@ void TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, in } ++Output; } + ++debugvertexcount; } if( p ) // jeśli jest wskaźnik do tablicy if( *p ) @@ -455,64 +460,73 @@ void TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, in *( *p ) = pt; ( *p )++; } // zapamiętanie brzegu jezdni + + assert( debugvertexcount <= debugvertexlimit ); } } else { - for( int j = 0; j < iNumShapePoints; ++j ) { - //ł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; - } - if( Output == nullptr ) { - // immediate mode + if( bRender ) { + for( int j = 0; j < iNumShapePoints; ++j ) { + //łuk z jednym profilem + pt = parallel1 * ( ShapePoints[ j ].x - fOffsetX ) + pos1; + pt.y += ShapePoints[ j ].y; if( false == Onlypositions ) { - ::glNormal3f( norm.x, norm.y, norm.z ); - ::glTexCoord2f( ShapePoints[ j ].z / Texturescale, tv1 ); + norm = ShapePoints[ j ].n.x * parallel1; + norm.y += ShapePoints[ j ].n.y; } - ::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( Output == nullptr ) { + // immediate mode + if( false == Onlypositions ) { + ::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; + } + ++debugvertexcount; + + pt = parallel2 * ShapePoints[ j ].x + pos2; + pt.y += ShapePoints[ j ].y; if( false == Onlypositions ) { - Output->nx = norm.x; - Output->ny = norm.y; - Output->nz = norm.z; - Output->u = ShapePoints[ j ].z / Texturescale; - Output->v = tv1; + norm = ShapePoints[ j ].n.x * parallel2; + norm.y += ShapePoints[ j ].n.y; } - ++Output; - } - 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; - } - if( Output == nullptr ) { - // immediate mode - if( false == Onlypositions ) { - ::glNormal3f( norm.x, norm.y, norm.z ); - ::glTexCoord2f( ShapePoints[ j ].z / Texturescale, tv2 ); + if( Output == nullptr ) { + // immediate mode + if( false == Onlypositions ) { + ::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 } - ::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; + 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; } - ++Output; + ++debugvertexcount; + + assert( debugvertexcount <= debugvertexlimit ); } } } @@ -526,6 +540,10 @@ void TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, in tv1 = tv2; } } + + assert( debugvertexcount == debugvertexlimit ); + + return debugvertexcount; }; void TSegment::Render() diff --git a/Segment.h b/Segment.h index aa303484..1c4c84ab 100644 --- a/Segment.h +++ b/Segment.h @@ -113,7 +113,7 @@ class TSegment r1 = fRoll1; r2 = fRoll2; } - void 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, 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); void Render(); inline double GetLength() { diff --git a/Track.cpp b/Track.cpp index 17cbef7f..56e21423 100644 --- a/Track.cpp +++ b/Track.cpp @@ -532,7 +532,7 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name) // na przechyłce doliczyć jeszcze pół przechyłki } if( fRadius != 0 ) // gdy podany promień - segsize = Min0R( 5.0, 0.2 + fabs( fRadius ) * 0.02 ); // do 250m - 5, potem 1 co 50m + segsize = clamp( 0.2 + fabs( fRadius ) * 0.02, 2.5, 10.0 ); else segsize = 10.0; // for straights, 10m per segment works good enough @@ -595,13 +595,14 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name) // na przechyłce doliczyć jeszcze pół przechyłki? } if (fRadiusTable[0] > 0) - segsize = Min0R(5.0, 0.2 + fRadiusTable[0] * 0.02); + segsize = clamp( 0.2 + fRadiusTable[0] * 0.02, 2.5, 5.0 ); else if (eType != tt_Cross) // dla skrzyżowań muszą być podane kontrolne { // jak promień zerowy, to przeliczamy punkty kontrolne cp1 = (p1 + p1 + p2) / 3.0 - p1; // jak jest prosty, to się zoptymalizuje cp2 = (p1 + p2 + p2) / 3.0 - p2; segsize = 5.0; } // ułomny prosty + if (!(cp1 == vector3(0, 0, 0)) && !(cp2 == vector3(0, 0, 0))) SwitchExtension->Segments[0]->Init(p1, p1 + cp1, p2 + cp2, p2, segsize, r1, r2); else @@ -624,7 +625,8 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name) } if (fRadiusTable[1] > 0) - segsize = Min0R(5.0, 0.2 + fRadiusTable[1] * 0.02); + segsize = clamp( 0.2 + fRadiusTable[ 1 ] * 0.02, 2.5, 5.0 ); + else if (eType != tt_Cross) // dla skrzyżowań muszą być podane kontrolne { // jak promień zerowy, to przeliczamy punkty kontrolne cp3 = (p3 + p3 + p4) / 3.0 - p3; // jak jest prosty, to się zoptymalizuje @@ -641,6 +643,7 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name) } else SwitchExtension->Segments[1]->Init(p3, p4, segsize, r3, r4); + if (eType == tt_Cross) { // Ra 2014-07: dla skrzyżowań będą dodatkowe segmenty SwitchExtension->Segments[2]->Init(p2, cp2 + p2, cp4 + p4, p4, segsize, r2, r4); // z punktu 2 do 4 @@ -1815,8 +1818,9 @@ int TTrack::RaArrayPrepare() return 0; }; -void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start) +int TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int const Vertexcount) { // wypełnianie tablic VBO + int debugvertexcount{ 0 }; // Ra: trzeba rozdzielić szyny od podsypki, aby móc grupować wg tekstur double fHTW = 0.5 * fabs(fTrackWidth); double side = fabs(fTexWidth); // szerokść podsypki na zewnątrz szyny albo pobocza @@ -1951,12 +1955,15 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start) 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); + debugvertexcount += Segment->RenderLoft(Vert, bpts1, iTrapezoid ? -4 : 4, fTexLength); + assert( debugvertexcount <= Vertexcount ); } 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); + debugvertexcount += Segment->RenderLoft(Vert, rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength); + assert( debugvertexcount <= Vertexcount ); + debugvertexcount += Segment->RenderLoft(Vert, rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength); + assert( debugvertexcount <= Vertexcount ); } break; case tt_Switch: // dla zwrotnicy dwa razy szyny @@ -1980,27 +1987,46 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start) } if (SwitchExtension->RightSwitch) { // nowa wersja z SPKS, ale odwrotnie lewa/prawa - SwitchExtension->Segments[0]->RenderLoft( Vert, rpts2, nnumPts, fTexLength); - SwitchExtension->Segments[0]->RenderLoft( Vert, rpts1, nnumPts, fTexLength, 1.0, 2 ); + int batch{ 0 }; + batch = SwitchExtension->Segments[0]->RenderLoft( Vert, rpts2, nnumPts, fTexLength); + debugvertexcount += batch; + assert( debugvertexcount <= Vertexcount ); + batch = SwitchExtension->Segments[0]->RenderLoft( Vert, rpts1, nnumPts, fTexLength, 1.0, 2 ); + debugvertexcount += batch; + assert( debugvertexcount <= Vertexcount ); SwitchExtension->iLeftVBO = Vert - Start; // indeks lewej iglicy - SwitchExtension->Segments[0]->RenderLoft( Vert, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 ); + batch = SwitchExtension->Segments[0]->RenderLoft( Vert, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 ); + debugvertexcount += batch; + assert( debugvertexcount <= Vertexcount ); 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 ); + batch = SwitchExtension->Segments[1]->RenderLoft( Vert, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 ); + debugvertexcount += batch; + assert( debugvertexcount <= Vertexcount ); + batch = SwitchExtension->Segments[1]->RenderLoft( Vert, rpts2, nnumPts, fTexLength, 1.0, 2 ); + debugvertexcount += batch; + assert( debugvertexcount <= Vertexcount ); + batch = SwitchExtension->Segments[1]->RenderLoft( Vert, rpts1, nnumPts, fTexLength ); + debugvertexcount += batch; + assert( debugvertexcount <= Vertexcount ); } else { // lewa działa lepiej niż prawa - 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ą + debugvertexcount += SwitchExtension->Segments[0]->RenderLoft( Vert, rpts1, nnumPts, fTexLength); // lewa szyna normalna cała + assert( debugvertexcount <= Vertexcount ); + debugvertexcount += SwitchExtension->Segments[0]->RenderLoft( Vert, rpts2, nnumPts, fTexLength, 1.0, 2 ); // prawa szyna za iglicą + assert( debugvertexcount <= Vertexcount ); SwitchExtension->iLeftVBO = Vert - Start; // indeks lewej iglicy - SwitchExtension->Segments[0]->RenderLoft( Vert, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2); // prawa iglica - + debugvertexcount += SwitchExtension->Segments[0]->RenderLoft( Vert, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2); // prawa iglica + assert( debugvertexcount <= Vertexcount ); + 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 + debugvertexcount += SwitchExtension->Segments[1]->RenderLoft( Vert, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1); // lewa iglica + assert( debugvertexcount <= Vertexcount ); + debugvertexcount += SwitchExtension->Segments[1]->RenderLoft( Vert, rpts1, nnumPts, fTexLength, 1.0, 2); // lewa szyna za iglicą + assert( debugvertexcount <= Vertexcount ); + debugvertexcount += SwitchExtension->Segments[1]->RenderLoft( Vert, rpts2, nnumPts, fTexLength); // prawa szyna normalnie cała + assert( debugvertexcount <= Vertexcount ); } } break; @@ -2034,7 +2060,8 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start) } 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); + debugvertexcount += Segment->RenderLoft(Vert, bpts1, iTrapezoid ? -2 : 2, fTexLength); + assert( debugvertexcount <= Vertexcount ); } if (TextureID2) { // pobocze drogi - poziome przy przechyłce (a może krawężnik i chodnik zrobić jak w Midtown Madness 2?) @@ -2114,16 +2141,24 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start) if( iTrapezoid ) // trapez albo przechyłki { // 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 - if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) - Segment->RenderLoft( Vert, rpts2, -3, fTexLength ); // tylko jeśli jest z lewej + if( ( fTexHeight1 >= 0.0 ) || ( slop != 0.0 ) ) { + debugvertexcount += Segment->RenderLoft( Vert, rpts1, -3, fTexLength ); // tylko jeśli jest z prawej + assert( debugvertexcount <= Vertexcount ); + } + if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) { + debugvertexcount += Segment->RenderLoft( Vert, rpts2, -3, fTexLength ); // tylko jeśli jest z lewej + assert( debugvertexcount <= Vertexcount ); + } } else { // pobocza zwykłe, brak przechyłki - if( ( fTexHeight1 >= 0.0 ) || ( slop != 0.0 ) ) - Segment->RenderLoft( Vert, rpts1, 3, fTexLength ); - if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) - Segment->RenderLoft( Vert, rpts2, 3, fTexLength ); + if( ( fTexHeight1 >= 0.0 ) || ( slop != 0.0 ) ) { + debugvertexcount += Segment->RenderLoft( Vert, rpts1, 3, fTexLength ); + assert( debugvertexcount <= Vertexcount ); + } + if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) { + debugvertexcount += Segment->RenderLoft( Vert, rpts2, 3, fTexLength ); + assert( debugvertexcount <= Vertexcount ); + } } } break; @@ -2262,18 +2297,25 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start) 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 ); + debugvertexcount += SwitchExtension->Segments[ 2 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); + assert( debugvertexcount <= Vertexcount ); + debugvertexcount += SwitchExtension->Segments[ 3 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); + assert( debugvertexcount <= Vertexcount ); + debugvertexcount += SwitchExtension->Segments[ 4 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); + assert( debugvertexcount <= Vertexcount ); + debugvertexcount += SwitchExtension->Segments[ 5 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); + assert( debugvertexcount <= Vertexcount ); } } 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 + debugvertexcount += SwitchExtension->Segments[ 2 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); // z P2 do P4 + assert( debugvertexcount <= Vertexcount ); + debugvertexcount += SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); // z P4 do P3=P1 (odwrócony) + assert( debugvertexcount <= Vertexcount ); + debugvertexcount += SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); // z P1 do P2 + assert( debugvertexcount <= Vertexcount ); } } } @@ -2304,6 +2346,7 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start) Vert->y = oxz.y; Vert->z = oxz.z; ++Vert; + ++debugvertexcount; for (i = SwitchExtension->iPoints - 2; i >= 0; --i) { Vert->nx = 0.0; @@ -2318,7 +2361,9 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start) Vert->y = SwitchExtension->vPoints[ i ].y; Vert->z = SwitchExtension->vPoints[ i ].z; ++Vert; + ++debugvertexcount; } + assert( debugvertexcount <= Vertexcount ); } break; } @@ -2357,7 +2402,8 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start) } 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); + debugvertexcount += Segment->RenderLoft(Vert, bpts1, iTrapezoid ? -2 : 2, fTexLength); + assert( debugvertexcount <= Vertexcount ); } if (TextureID2) { // pobocze drogi - poziome przy przechyłce (a może krawężnik i chodnik zrobić jak w @@ -2379,19 +2425,24 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start) 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); + debugvertexcount += Segment->RenderLoft(Vert, rpts1, -3, fTexLength); + assert( debugvertexcount <= Vertexcount ); + debugvertexcount += Segment->RenderLoft(Vert, rpts2, -3, fTexLength); + assert( debugvertexcount <= Vertexcount ); } else { // pobocza zwykłe, brak przechyłki - Segment->RenderLoft(Vert, rpts1, 3, fTexLength); - Segment->RenderLoft(Vert, rpts2, 3, fTexLength); + debugvertexcount += Segment->RenderLoft(Vert, rpts1, 3, fTexLength); + assert( debugvertexcount <= Vertexcount ); + debugvertexcount += Segment->RenderLoft(Vert, rpts2, 3, fTexLength); + assert( debugvertexcount <= Vertexcount ); } } } } break; } + return debugvertexcount; }; void TTrack::RaRenderVBO( int iPtr ) { // renderowanie z użyciem VBO @@ -2936,8 +2987,9 @@ TTrack * TTrack::RaAnimate(GLuint const Vertexbuffer) int size = RaArrayPrepare(); // wielkość tabeli potrzebna dla tej obrotnicy CVertNormTex *Vert = new CVertNormTex[size]; // bufor roboczy // CVertNormTex *v=Vert; //zmieniane przez - RaArrayFill(Vert, Vert - SwitchExtension->iLeftVBO); // iLeftVBO powinno zostać niezmienione - glBufferSubData( + auto const debugvertexcount = RaArrayFill(Vert, Vert - SwitchExtension->iLeftVBO, size); // iLeftVBO powinno zostać niezmienione + assert( debugvertexcount == size ); + ::glBufferSubData( GL_ARRAY_BUFFER, SwitchExtension->iLeftVBO * sizeof(CVertNormTex), size * sizeof(CVertNormTex), Vert); // wysłanie fragmentu bufora VBO } diff --git a/Track.h b/Track.h index 6809afc6..8cab1b1d 100644 --- a/Track.h +++ b/Track.h @@ -240,7 +240,7 @@ class TTrack : public Resource void Render(); // renderowanie z Display Lists int RaArrayPrepare(); // zliczanie rozmiaru dla VBO sektroa - void RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start); // wypełnianie VBO + int RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int const Vertexcount); // wypełnianie VBO void RaRenderVBO(int iPtr); // renderowanie z VBO sektora void RenderDyn(); // renderowanie nieprzezroczystych pojazdów (oba tryby) void RenderDynAlpha(); // renderowanie przezroczystych pojazdów (oba tryby) diff --git a/Traction.cpp b/Traction.cpp index 4aa4d8d3..8324854a 100644 --- a/Traction.cpp +++ b/Traction.cpp @@ -324,8 +324,10 @@ int TTraction::RaArrayPrepare() return iLines; }; -void TTraction::RaArrayFill(CVertNormTex *Vert) +int TTraction::RaArrayFill(CVertNormTex *Vert) { // wypełnianie tablic VBO + int debugvertexcount{ 0 }; + double ddp = std::hypot(pPoint2.x - pPoint1.x, pPoint2.z - pPoint1.z); if (Wires == 2) WireOffset = 0; @@ -334,10 +336,12 @@ void TTraction::RaArrayFill(CVertNormTex *Vert) Vert->y = pPoint1.y; Vert->z = pPoint1.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset; ++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; + ++debugvertexcount; // Nie wiem co 'Marcin Math3D::vector3 pt1, pt2, pt3, pt4, v1, v2; v1 = pPoint4 - pPoint3; @@ -355,6 +359,7 @@ void TTraction::RaArrayFill(CVertNormTex *Vert) Vert->y = pPoint3.y; Vert->z = pPoint3.z; ++Vert; + ++debugvertexcount; for (int i = 0; i < iNumSections - 1; ++i) { pt3 = pPoint3 + v1 * f; @@ -366,6 +371,7 @@ void TTraction::RaArrayFill(CVertNormTex *Vert) Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference; Vert->z = pt3.z; ++Vert; + ++debugvertexcount; } f += step; } @@ -373,6 +379,7 @@ void TTraction::RaArrayFill(CVertNormTex *Vert) Vert->y = pPoint4.y; Vert->z = pPoint4.z; ++Vert; + ++debugvertexcount; } // Drugi przewod jezdny 'Winger if (Wires > 2) @@ -381,10 +388,12 @@ void TTraction::RaArrayFill(CVertNormTex *Vert) Vert->y = pPoint1.y; Vert->z = pPoint1.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset; ++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; + ++debugvertexcount; } f = step; @@ -394,6 +403,7 @@ void TTraction::RaArrayFill(CVertNormTex *Vert) Vert->y = pPoint3.y - 0.65f * fHeightDifference; Vert->z = pPoint3.z; ++Vert; + ++debugvertexcount; for( int i = 0; i < iNumSections - 1; ++i ) { pt3 = pPoint3 + v1 * f; t = ( 1 - std::fabs( f - mid ) * 2 ); @@ -405,11 +415,14 @@ void TTraction::RaArrayFill(CVertNormTex *Vert) 0.05 ); Vert->z = pt3.z; ++Vert; + ++debugvertexcount; f += step; } Vert->x = pPoint4.x; Vert->y = pPoint4.y - 0.65f * fHeightDifference; Vert->z = pPoint4.z; + ++Vert; + ++debugvertexcount; } f = step; @@ -430,20 +443,24 @@ void TTraction::RaArrayFill(CVertNormTex *Vert) Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - ( ( i == 0 ) || ( i == iNumSections - 2 ) ? flo : flo1 ); Vert->z = pt3.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; + ++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; + ++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; + ++debugvertexcount; } if( ( ( Wires == 4 ) && ( ( i == 1 ) @@ -452,14 +469,17 @@ void TTraction::RaArrayFill(CVertNormTex *Vert) Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - 0.05; Vert->z = pt3.z; ++Vert; + ++debugvertexcount; Vert->x = pt3.x; Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference; Vert->z = pt3.z; ++Vert; + ++debugvertexcount; } f += step; } } + return debugvertexcount; }; void TTraction::RenderVBO(float mgn, int iPtr) diff --git a/Traction.h b/Traction.h index e1484819..e276bf59 100644 --- a/Traction.h +++ b/Traction.h @@ -68,7 +68,7 @@ class TTraction // virtual void SelectedRender(); void RenderDL(float mgn); int RaArrayPrepare(); - void RaArrayFill(CVertNormTex *Vert); + int RaArrayFill(CVertNormTex *Vert); void RenderVBO(float mgn, int iPtr); int TestPoint(Math3D::vector3 *Point); void Connect(int my, TTraction *with, int to); diff --git a/version.h b/version.h index 5ecf5416..b942025d 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 17 -#define VERSION_MINOR 517 +#define VERSION_MINOR 519 #define VERSION_REVISION 0