diff --git a/Button.cpp b/Button.cpp index 06211b1d..a673bbfd 100644 --- a/Button.cpp +++ b/Button.cpp @@ -77,7 +77,7 @@ void TButton::Load(cParser &Parser, TModel3d *pModel1, TModel3d *pModel2) { bool TButton::Load_mapping( cParser &Input ) { - if( false == Input.getTokens( 2, true, ", " ) ) { + if( false == Input.getTokens( 2, true, " ,\n\r\t" ) ) { return false; } diff --git a/Console.cpp b/Console.cpp index 076d4332..5f67d082 100644 --- a/Console.cpp +++ b/Console.cpp @@ -359,7 +359,7 @@ void Console::ValueSet(int x, double y) WriteLog("CalibrateOutDebugInfo: oryginal=" + std::to_string(y), false); if (Global::fCalibrateOutMax[x] > 0) { - y = Global::CutValueToRange(0, y, Global::fCalibrateOutMax[x]); + y = clamp( y, 0.0, Global::fCalibrateOutMax[x]); if (Global::iCalibrateOutDebugInfo == x) WriteLog(" cutted=" + std::to_string(y), false); y = y / Global::fCalibrateOutMax[x]; // sprowadzenie do <0,1> jeśli podana diff --git a/Driver.cpp b/Driver.cpp index ed929c83..a3d39221 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -4356,7 +4356,7 @@ bool TController::UpdateSituation(double dt) if (ActualProximityDist < fMaxProximityDist) { // jak minął już maksymalny dystans po prostu hamuj (niski stopień) // ma stanąć, a jest w drodze hamowania albo ma jechać - VelDesired = VelNext; + VelDesired = Global::Min0RSpeed( VelDesired, VelNext ); if( VelDesired == 0.0 ) { // hamowanie tak, aby stanąć AccDesired = ( VelNext * VelNext - vel * vel ) / ( 25.92 * ( ActualProximityDist + 0.1 - 0.5*fMinProximityDist ) ); @@ -4452,19 +4452,6 @@ bool TController::UpdateSituation(double dt) } // koniec predkosci aktualnej -#ifdef DEBUGFAC - if (fAccThreshold > -0.3) // bez sensu, ale dla towarowych korzystnie - { // Ra 2014-03: to nie uwzględnia odległości i zaczyna hamować, jak tylko zobaczy - // W4 - if ((AccDesired > 0.0) && - (VelNext >= 0.0)) // wybieg bądź lekkie hamowanie, warunki byly zamienione - if (vel > VelNext + 100.0) // lepiej zaczac hamowac - AccDesired = fAccThreshold; - else if (vel > VelNext + 70.0) - AccDesired = 0.0; // nie spiesz się, bo będzie hamowanie - // koniec wybiegu i hamowania - } -#endif // DEBUGFAC // last step sanity check, until the whole calculation is straightened out AccDesired = std::min( AccDesired, AccPreferred ); diff --git a/DynObj.h b/DynObj.h index 8095c7f3..59efe6e2 100644 --- a/DynObj.h +++ b/DynObj.h @@ -186,7 +186,7 @@ public: // modele składowe pojazdu TModel3d *mdLoad; // model zmiennego ładunku TModel3d *mdKabina; // model kabiny dla użytkownika; McZapkie-030303: to z train.h TModel3d *mdLowPolyInt; // ABu 010305: wnetrze lowpoly - float3 InteriorLight { 0.9f * 255.0f / 255.0f, 0.9f * 216.0f / 255.0f, 0.9f * 176.0f / 255.0f }; // tungsten light. TODO: allow definition of light type? + glm::vec3 InteriorLight { 0.9f * 255.f / 255.f, 0.9f * 216.f / 255.f, 0.9f * 176.f / 255.f }; // tungsten light. TODO: allow definition of light type? float InteriorLightLevel { 0.0f }; // current level of interior lighting struct section_light { TSubModel *compartment; diff --git a/Event.cpp b/Event.cpp index a56c5cdf..ae9836c3 100644 --- a/Event.cpp +++ b/Event.cpp @@ -431,8 +431,7 @@ void TEvent::Load(cParser *parser, vector3 *org) *parser >> token; break; case tp_Exit: - while ((ptr = strchr(strdup(asNodeName.c_str()), '_')) != NULL) - *ptr = ' '; + asNodeName = ExchangeCharInString( asNodeName, '_', ' ' ); parser->getTokens(); *parser >> token; break; diff --git a/Gauge.cpp b/Gauge.cpp index c52de766..2c262268 100644 --- a/Gauge.cpp +++ b/Gauge.cpp @@ -116,7 +116,7 @@ bool TGauge::Load(cParser &Parser, TModel3d *md1, TModel3d *md2, double mul) { bool TGauge::Load_mapping( cParser &Input ) { - if( false == Input.getTokens( 2, true, ", " ) ) { + if( false == Input.getTokens( 2, true, ", \n\r\t" ) ) { return false; } diff --git a/Globals.cpp b/Globals.cpp index 323c849d..f83d9e89 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -1313,10 +1313,3 @@ double Global::Min0RSpeed(double vel1, double vel2) } return std::min(vel1, vel2); }; - -double Global::CutValueToRange(double min, double value, double max) -{ // przycinanie wartosci do podanych granic - value = Max0R(value, min); - value = Min0R(value, max); - return value; -}; diff --git a/Globals.h b/Globals.h index db70de30..37fefd65 100644 --- a/Globals.h +++ b/Globals.h @@ -336,7 +336,6 @@ class Global static bool DoEvents(); static std::string Bezogonkow(std::string str, bool _ = false); static double Min0RSpeed(double vel1, double vel2); - static double CutValueToRange(double min, double value, double max); // maciek001: zmienne dla MWD static bool bMWDmasterEnable; // główne włączenie portu COM diff --git a/Ground.cpp b/Ground.cpp index d5f309dc..6c5b29e1 100644 --- a/Ground.cpp +++ b/Ground.cpp @@ -490,12 +490,11 @@ TGroundRect::NodeAdd( TGroundNode *Node ) { matchingnode->pCenter, Node->pCenter, static_cast( Node->iNumVerts ) / ( Node->iNumVerts + matchingnode->iNumVerts ) ); matchingnode->iNumVerts += Node->iNumVerts; - matchingnode->Piece->vertices.resize( matchingnode->iNumVerts, TGroundVertex() ); matchingnode->Piece->vertices.insert( std::end( matchingnode->Piece->vertices ), std::begin( Node->Piece->vertices ), std::end( Node->Piece->vertices ) ); // clear content of the node we're copying. a minor memory saving at best, but still a saving - Node->Piece->vertices.swap( std::vector() ); + std::vector().swap( Node->Piece->vertices ); Node->iNumVerts = 0; // since we've put the data in existing node we can skip adding the new one... return; @@ -578,7 +577,6 @@ void TGround::Free() Current = Current->nNext; delete tmpn; } - iNumNodes = 0; // RootNode=NULL; nRootDynamic = NULL; } @@ -694,7 +692,6 @@ TGround::convert_terrain( TSubModel const *Submodel ) { groundnode->nNext = nRootOfType[ groundnode->iType ]; // ustawienie nowego na początku listy nRootOfType[ groundnode->iType ] = groundnode; - ++iNumNodes; } else { delete groundnode; @@ -791,7 +788,6 @@ void TGround::RaTriangleDivider(TGroundNode *node) ntri->bVisible = node->bVisible; // a są jakieś niewidoczne? ntri->nNext = nRootOfType[GL_TRIANGLES]; nRootOfType[GL_TRIANGLES] = ntri; // dopisanie z przodu do listy - ++iNumNodes; ntri->iNumVerts = 3; ntri->Piece->vertices.resize( 3 ); switch (divide & 3) @@ -1773,7 +1769,6 @@ bool TGround::Init(std::string File) // pTrain=NULL; pOrigin = aRotate = vector3(0, 0, 0); // zerowanie przesunięcia i obrotu std::string str; - // TFileStream *fs; // int size; std::string subpath = Global::asCurrentSceneryPath; // "scenery/"; cParser parser(File, cParser::buffer_FILE, subpath, Global::bLoadTraction); @@ -1782,7 +1777,6 @@ bool TGround::Init(std::string File) std::stack OriginStack; // stos zagnieżdżenia origin TGroundNode *LastNode = nullptr; // do użycia w trainset - iNumNodes = 0; token = ""; parser.getTokens(); parser >> token; @@ -1839,7 +1833,6 @@ bool TGround::Init(std::string File) LastNode->nNext = nRootOfType[ LastNode->iType ]; // ustawienie nowego na początku listy nRootOfType[ LastNode->iType ] = LastNode; - ++iNumNodes; } else { // jeśli jest pojazdem if( ( LastNode->DynamicObject->Mechanik != nullptr ) @@ -2666,7 +2659,6 @@ void TGround::InitTracks() Current->nNext = nRootOfType[TP_MEMCELL]; // to nie powinno tutaj być, bo robi się śmietnik nRootOfType[TP_MEMCELL] = Current; - iNumNodes++; p->pMemCell = Current->MemCell; // wskaźnik komóki przekazany do odcinka izolowanego } p = p->Next(); @@ -2705,7 +2697,6 @@ void TGround::InitTraction() nTemp->nNext = nRootOfType[nTemp->iType]; // ostatni dodany dołączamy na końcu // nowego nRootOfType[nTemp->iType] = nTemp; // ustawienie nowego na początku listy - iNumNodes++; } } for (nCurrent = nRootOfType[TP_TRACTION]; nCurrent; nCurrent = nCurrent->nNext) @@ -3151,9 +3142,8 @@ bool TGround::EventConditon(TEvent *e) return (e->Params[9].asTrack->IsEmpty()); else if (e->iFlags & conditional_propability) { - double rprobability = 1.0 * rand() / RAND_MAX; - WriteLog("Random integer: " + std::to_string(rprobability) + "/" + - std::to_string(e->Params[10].asdouble)); + double rprobability = Random(); + WriteLog("Random integer: " + std::to_string(rprobability) + " / " + std::to_string(e->Params[10].asdouble)); return (e->Params[10].asdouble > rprobability); } else if (e->iFlags & conditional_memcompare) diff --git a/Ground.h b/Ground.h index 21dd6399..a35f69f5 100644 --- a/Ground.h +++ b/Ground.h @@ -151,13 +151,8 @@ public: TGroundNode(); TGroundNode(TGroundNodeType t); ~TGroundNode(); -/* - void Init(int n); -*/ + void InitNormals(); -/* - void Release(); -*/ void RenderHidden(); // obsługa dźwięków i wyzwalaczy zdarzeń }; @@ -205,7 +200,6 @@ class TSubRect : /*public Resource,*/ public CMesh // Ra: trzeba sprawdzić wydajność siatki const int iNumSubRects = 5; // na ile dzielimy kilometr const int iNumRects = 500; -// const double fHalfNumRects=iNumRects/2.0; //połowa do wyznaczenia środka const int iTotalNumSubRects = iNumRects * iNumSubRects; const double fHalfTotalNumSubRects = iTotalNumSubRects / 2.0; const double fSubRectSize = 1000.0 / iNumSubRects; @@ -255,27 +249,22 @@ class TGround { friend class opengl_renderer; - vector3 CameraDirection; // zmienna robocza przy renderowaniu - int const *iRange = nullptr; // tabela widoczności + TGroundRect Rects[ iNumRects ][ iNumRects ]; // mapa kwadratów kilometrowych + TSubRect srGlobal; // zawiera obiekty globalne (na razie wyzwalacze czasowe) TGroundNode *nRootDynamic = nullptr; // lista pojazdów - TGroundRect Rects[iNumRects][iNumRects]; // mapa kwadratów kilometrowych + TGroundNode *nRootOfType[ TP_LAST ]; // tablica grupująca obiekty, przyspiesza szukanie TEvent *RootEvent = nullptr; // lista zdarzeń TEvent *QueryRootEvent = nullptr, *tmpEvent = nullptr; -/* - TSubRect *pRendered[1500]; // lista renderowanych sektorów -*/ - int iNumNodes = 0; - vector3 pOrigin; - vector3 aRotate; - bool bInitDone = false; - TGroundNode *nRootOfType[TP_LAST]; // tablica grupująca obiekty, przyspiesza szukanie - TSubRect srGlobal; // zawiera obiekty globalne (na razie wyzwalacze czasowe) typedef std::unordered_map event_map; event_map m_eventmap; TNames m_trackmap; light_array m_lights; // collection of dynamic light sources present in the scene + vector3 pOrigin; + vector3 aRotate; + bool bInitDone = false; + private: // metody prywatne bool EventConditon(TEvent *e); @@ -333,9 +322,6 @@ class TGround public: void WyslijEvent(const std::string &e, const std::string &d); -/* - int iRendered; // ilość renderowanych sektorów, pobierana przy pokazywniu FPS -*/ void WyslijString(const std::string &t, int n); void WyslijWolny(const std::string &t); void WyslijNamiary(TGroundNode *t); @@ -355,4 +341,5 @@ class TGround void IsolatedBusy(const std::string t); void Silence(vector3 gdzie); }; + //--------------------------------------------------------------------------- diff --git a/McZapkie/mctools.cpp b/McZapkie/mctools.cpp index ab66f304..f249de8f 100644 --- a/McZapkie/mctools.cpp +++ b/McZapkie/mctools.cpp @@ -114,13 +114,14 @@ std::string DWE(std::string s) /*Delete After Equal sign*/ return s; } -std::string ExchangeCharInString( std::string const &Source, char const &From, char const &To ) +std::string ExchangeCharInString( std::string const &Source, char const From, char const To ) { std::string replacement; replacement.reserve( Source.size() ); - std::for_each(Source.cbegin(), Source.cend(), [&](char const idx) { - if( idx != From ) { replacement += idx; } - else { replacement += To; } - } ); + std::for_each( + std::begin( Source ), std::end( Source ), + [&](char const idx) { + if( idx != From ) { replacement += idx; } + else { replacement += To; } } ); return replacement; } diff --git a/McZapkie/mctools.h b/McZapkie/mctools.h index 9af628f7..9c0c4f5d 100644 --- a/McZapkie/mctools.h +++ b/McZapkie/mctools.h @@ -75,7 +75,7 @@ bool FuzzyLogicAI(double Test, double Threshold, double Probability); /*operacje na stringach*/ std::string DUE(std::string s); /*Delete Until Equal sign*/ std::string DWE(std::string s); /*Delete While Equal sign*/ -std::string ExchangeCharInString(std::string const &s, const char &aim, const char &target); // zamienia jeden znak na drugi +std::string ExchangeCharInString( std::string const &Source, char const From, char const To ); // zamienia jeden znak na drugi std::vector &Split(const std::string &s, char delim, std::vector &elems); std::vector Split(const std::string &s, char delim); //std::vector Split(const std::string &s); diff --git a/Track.cpp b/Track.cpp index 528b955c..dddd9e59 100644 --- a/Track.cpp +++ b/Track.cpp @@ -762,12 +762,6 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name) iAction |= 0x40; // flaga opuszczenia pantografu (tor uwzględniany w skanowaniu jako // ograniczenie dla pantografujących) } - else if (str == "colides") - { // informacja o stanie sieci: 0-jazda bezprądowa, >0-z opuszczonym i ograniczeniem prędkości - parser->getTokens(); - *parser >> token; - // trColides=; //tor kolizyjny, na którym trzeba sprawdzać pojazdy pod kątem zderzenia - } else ErrorLog("Unknown property: \"" + str + "\" in track \"" + name + "\""); parser->getTokens(); diff --git a/Track.h b/Track.h index 2211ff10..7b791a05 100644 --- a/Track.h +++ b/Track.h @@ -139,9 +139,7 @@ private: float fTexHeight1 = 0.6f; // wysokość brzegu względem trajektorii float fTexWidth = 0.9f; // szerokość boku float fTexSlope = 0.9f; -/* - GLuint DisplayListID = 0; -*/ + material_handle m_material1 = 0; // tekstura szyn albo nawierzchni material_handle m_material2 = 0; // tekstura automatycznej podsypki albo pobocza typedef std::vector geometryhandle_sequence; @@ -187,7 +185,6 @@ public: bool ScannedFlag = false; // McZapkie: do zaznaczania kolorem torów skanowanych przez AI TTraction *hvOverhead = nullptr; // drut zasilający do szybkiego znalezienia (nie używany) TGroundNode *nFouling[ 2 ]; // współrzędne ukresu albo oporu kozła - TTrack *trColides = nullptr; // tor kolizyjny, na którym trzeba sprawdzać pojazdy pod kątem zderzenia TTrack(TGroundNode *g); ~TTrack(); @@ -225,17 +222,8 @@ public: bool CheckDynamicObject(TDynamicObject *Dynamic); bool AddDynamicObject(TDynamicObject *Dynamic); bool RemoveDynamicObject(TDynamicObject *Dynamic); -/* - void Release(); - void Compile(GLuint tex = 0); - void Render(); // renderowanie z Display Lists - int RaArrayPrepare(); // zliczanie rozmiaru dla VBO sektroa -*/ void create_geometry(geometrybank_handle const &Bank); // wypełnianie VBO -/* - void RaRenderVBO(int iPtr); // renderowanie z VBO sektora -*/ void RenderDynSounds(); // odtwarzanie dźwięków pojazdów jest niezależne od ich wyświetlania void RaOwnerSet(TSubRect *o) { diff --git a/Train.cpp b/Train.cpp index c46ff0bf..5a1e2671 100644 --- a/Train.cpp +++ b/Train.cpp @@ -4510,8 +4510,8 @@ bool TTrain::Update( double const Deltatime ) if (mvOccupied->BrakeHandle == FV4a) { double b = Console::AnalogCalibrateGet(0); - b = b * 8 - 2; - b = Global::CutValueToRange(-2.0, b, mvOccupied->BrakeCtrlPosNo); // przycięcie zmiennej do granic + b = b * 8.0 - 2.0; + b = clamp( b, -2.0, mvOccupied->BrakeCtrlPosNo ); // przycięcie zmiennej do granic if (Global::bMWDdebugEnable && Global::iMWDDebugMode & 4) WriteLog("FV4a break position = " + to_string(b)); ggBrakeCtrl.UpdateValue(b); // przesów bez zaokrąglenia mvOccupied->BrakeLevelSet(b); @@ -4519,8 +4519,8 @@ bool TTrain::Update( double const Deltatime ) if (mvOccupied->BrakeHandle == FVel6) // może można usunąć ograniczenie do FV4a i FVel6? { double b = Console::AnalogCalibrateGet(0); - b = b * 7 - 1; - b = Global::CutValueToRange(-1.0, b, mvOccupied->BrakeCtrlPosNo); // przycięcie zmiennej do granic + b = b * 7.0 - 1.0; + b = clamp( b, -1.0, mvOccupied->BrakeCtrlPosNo ); // przycięcie zmiennej do granic if (Global::bMWDdebugEnable && Global::iMWDDebugMode & 4) WriteLog("FVel6 break position = " + to_string(b)); ggBrakeCtrl.UpdateValue(b); // przesów bez zaokrąglenia mvOccupied->BrakeLevelSet(b); @@ -4543,8 +4543,8 @@ bool TTrain::Update( double const Deltatime ) if ((mvOccupied->BrakeLocHandle == FD1)) { double b = Console::AnalogCalibrateGet(1); - b *= 10; - b = Global::CutValueToRange(0.0, b, LocalBrakePosNo); // przycięcie zmiennej do granic + b *= 10.0; + b = clamp( b, 0.0, LocalBrakePosNo); // przycięcie zmiennej do granic ggLocalBrake.UpdateValue(b); // przesów bez zaokrąglenia if (Global::bMWDdebugEnable && Global::iMWDDebugMode & 4) WriteLog("FD1 break position = " + to_string(b)); mvOccupied->LocalBrakePos = diff --git a/renderer.cpp b/renderer.cpp index 4cd8d5da..530e4c25 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -1848,8 +1848,7 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) { if( Dynamic->InteriorLightLevel > 0.0f ) { // crude way to light the cabin, until we have something more complete in place - auto const cablight = Dynamic->InteriorLight * Dynamic->InteriorLightLevel; - ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, &cablight.x ); + ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( Dynamic->InteriorLight * Dynamic->InteriorLightLevel ) ); } Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance ); @@ -1941,8 +1940,7 @@ opengl_renderer::Render_cab( TDynamicObject *Dynamic ) { } if( Dynamic->InteriorLightLevel > 0.0f ) { // crude way to light the cabin, until we have something more complete in place - auto const cablight = Dynamic->InteriorLight * Dynamic->InteriorLightLevel; - ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, &cablight.x ); + ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( Dynamic->InteriorLight * Dynamic->InteriorLightLevel ) ); } // render Render( Dynamic->mdKabina, Dynamic->Material(), 0.0 ); @@ -2588,8 +2586,7 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) { if( Dynamic->InteriorLightLevel > 0.0f ) { // crude way to light the cabin, until we have something more complete in place - auto const cablight = Dynamic->InteriorLight * Dynamic->InteriorLightLevel; - ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, &cablight.x ); + ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( Dynamic->InteriorLight * Dynamic->InteriorLightLevel ) ); } Render_Alpha( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance ); diff --git a/skydome.cpp b/skydome.cpp index 7d136971..342a8e00 100644 --- a/skydome.cpp +++ b/skydome.cpp @@ -122,11 +122,11 @@ void CSkyDome::Render() { // build the buffers ::glGenBuffers( 1, &m_vertexbuffer ); ::glBindBuffer( GL_ARRAY_BUFFER, m_vertexbuffer ); - ::glBufferData( GL_ARRAY_BUFFER, m_vertices.size() * sizeof( float3 ), m_vertices.data(), GL_STATIC_DRAW ); + ::glBufferData( GL_ARRAY_BUFFER, m_vertices.size() * sizeof( glm::vec3 ), m_vertices.data(), GL_STATIC_DRAW ); ::glGenBuffers( 1, &m_coloursbuffer ); ::glBindBuffer( GL_ARRAY_BUFFER, m_coloursbuffer ); - ::glBufferData( GL_ARRAY_BUFFER, m_colours.size() * sizeof( float3 ), m_colours.data(), GL_DYNAMIC_DRAW ); + ::glBufferData( GL_ARRAY_BUFFER, m_colours.size() * sizeof( glm::vec3 ), m_colours.data(), GL_DYNAMIC_DRAW ); ::glGenBuffers( 1, &m_indexbuffer ); ::glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_indexbuffer ); @@ -138,10 +138,10 @@ void CSkyDome::Render() { ::glEnableClientState( GL_COLOR_ARRAY ); // positions ::glBindBuffer( GL_ARRAY_BUFFER, m_vertexbuffer ); - ::glVertexPointer( 3, GL_FLOAT, sizeof( float3 ), reinterpret_cast( 0 ) ); + ::glVertexPointer( 3, GL_FLOAT, sizeof( glm::vec3 ), reinterpret_cast( 0 ) ); // colours ::glBindBuffer( GL_ARRAY_BUFFER, m_coloursbuffer ); - ::glColorPointer( 3, GL_FLOAT, sizeof( float3 ), reinterpret_cast( 0 ) ); + ::glColorPointer( 3, GL_FLOAT, sizeof( glm::vec3 ), reinterpret_cast( 0 ) ); // indices ::glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_indexbuffer ); ::glDrawElements( GL_TRIANGLES, static_cast( m_indices.size() ), GL_UNSIGNED_SHORT, reinterpret_cast( 0 ) ); @@ -345,7 +345,7 @@ void CSkyDome::RebuildColors() { if( m_coloursbuffer != -1 ) { // the colour buffer was already initialized, so on this run we update its content ::glBindBuffer( GL_ARRAY_BUFFER, m_coloursbuffer ); - ::glBufferSubData( GL_ARRAY_BUFFER, 0, m_colours.size() * sizeof( float3 ), m_colours.data() ); + ::glBufferSubData( GL_ARRAY_BUFFER, 0, m_colours.size() * sizeof( glm::vec3 ), m_colours.data() ); } }