void AppWindow::initPrograms () { // Init my scene objects: _axis.init (); _floor.init( "../texture/_image.bmp", textures); _floor.build( 20.0f, -5.0f, 20.0f, textures); _side.init(); _side.build(25.0f, 20.0f, 20.0f, 25, textures); _sun.init(); _building.load("../models/The_City.obj"); //_building.scale(.7f); _city.init(); _city.build(_building); //initiate models _model.init(); _model2.init(); _model3.init(); _model4.init(); _model5.init(); _model6.init(); // set light: _light.set ( GsVec(0,0,10), GsColor(90,90,90,255), GsColor::white, GsColor::white ); _shadow.set(GsVec(0, 0, 10), GsColor(0, 0, 0, 255), GsColor::black, GsColor::black); // Load demo model: loadModel ( 1 ); }
void Snake::build(int size, std::vector<float>& x, std::vector<float>& y, float right, float up ) { //int i; float r = 0.01f; const float d = r / 20.0f; const float depth = 0.0; ranX = 1.0; //(rand() % 100) / 100; ranY = 2.0;//(rand() % 100) / 100; P.clear(); C.clear(); // set size to zero, just in case for (int i = 0; i < size; i++) { if (i == 0) { P.push_back(GsVec(right,up, 0.0f)); P.push_back(GsVec(x[i], y[i], 0.0f)); for (int i = 0; i < 2; i++) C.push_back(GsColor::lightgray); } else { P.push_back(GsVec(x[i-1], y[i-1], 0.0f)); P.push_back(GsVec(x[i], y[i], 0.0f)); for (int i = 0; i < 2; i++) C.push_back(GsColor::lightgray); } } // send data to OpenGL buffers: glBindBuffer(GL_ARRAY_BUFFER, buf[0]); glBufferData(GL_ARRAY_BUFFER, P.size() * 3 * sizeof(float), &P[0], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, buf[1]); glBufferData(GL_ARRAY_BUFFER, C.size() * 4 * sizeof(gsbyte), &C[0], GL_STATIC_DRAW); // save size so that we can free our buffers and later just draw the OpenGL arrays: _numpoints = P.size(); // free non-needed memory: P.resize(0); C.resize(0); }
void AppWindow::initPrograms () { // We are not directly initializing glsl programs here, instead, each scene object // initializes its own program(s). This makes sharing more difficult but is probably easier // to manage. // Init my scene objects: _axis.init (); _texturedCylinder.init (); _lines.init (); // set light: _light.set ( GsVec(0,0,10), GsColor(90,90,90,255), GsColor::white, GsColor::white ); // Load demo model: _texturedCylinder.build(rt, rb, 1.0f, numfaces); // Build normals object: _lines.build ( _texturedCylinder.NL, GsColor::yellow ); }
void SoCapsule::build(float len, float rt, float rb, int degree) { P.clear(); C.clear(); P.reserve(18); C.reserve(18); // reserve space to avoid re-allocations from the calls below // circle radius rt, vetex at cos, sin, -len/2 double thetaInc = M_PI /2; for (double p = 0; p < 2* M_PI ; p += thetaInc) { for (double d = 0; d < 2 * M_PI; d += thetaInc) { std::vector<GsVec> Q; Q.push_back(GsVec(cos(d)*sin(p), sin(d)*sin(p), cos(p))); Q.push_back(GsVec(cos(d+ thetaInc)*sin(p), sin(d+ thetaInc)*sin(p), cos(p))); Q.push_back(GsVec(cos(d)*sin(p + thetaInc), sin(d)*sin(p + thetaInc), cos(p + thetaInc))); subdiv(Q, degree); std::vector<GsVec> S; S.push_back(GsVec(cos(d + thetaInc)*sin(p+thetaInc), sin(d + thetaInc)*sin(p+thetaInc), cos(p+thetaInc))); S.push_back(GsVec(cos(d + thetaInc)*sin(p), sin(d + thetaInc)*sin(p), cos(p))); S.push_back(GsVec(cos(d)*sin(p + thetaInc), sin(d)*sin(p + thetaInc), cos(p + thetaInc))); subdiv(S, degree); } } // circle radius rb, vertex at cos, sin, len/2 // send data to OpenGL buffers: glBindBuffer(GL_ARRAY_BUFFER, buf[0]); glBufferData(GL_ARRAY_BUFFER, P.size() * 3 * sizeof(float), &P[0], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, buf[1]); glBufferData(GL_ARRAY_BUFFER, C.size() * 4 * sizeof(gsbyte), &C[0], GL_STATIC_DRAW); _numpoints = P.size(); P.resize(0); C.resize(0); }
void SoCapsule::build ( float len, float rt, float rb, int nfaces ) { P.clear(); C.clear(); // set size to zero, just in case float hlen = len/2.0f; int levels = std::ceil(static_cast<float>(nfaces) / 2.0f); float faceAngularHeight = (static_cast<float>(M_PI) / 2.0) / static_cast<float>(levels); float faceAngularLength = (2.0 * static_cast<float>(M_PI)) / static_cast<float>(nfaces); int vertices = 2 + (2*levels + 1)*(nfaces * 6); // Reserve space for the capsule vertices P.reserve(vertices); C.reserve(vertices); // Generate the coordinates for the capsule body std::vector<GsVec> bodyTopCoordinates; std::vector<GsVec> bodyBottomCoordinates; bodyTopCoordinates.reserve(nfaces); bodyBottomCoordinates.reserve(nfaces); // Compute the tube section of the capsule for(int i = 0; i < nfaces; i++) { float p = static_cast<float>(i) * faceAngularLength; bodyTopCoordinates.push_back(GsVec(rt * std::cos(p), hlen, rt * std::sin(p))); bodyBottomCoordinates.push_back(GsVec(rb * std::cos(p), -hlen, rb * std::sin(p))); } pushLevel(P, C, bodyTopCoordinates, bodyBottomCoordinates, nfaces); // Compute the top of the capsule std::vector<GsVec>& previousTopVector = bodyTopCoordinates; std::vector<GsVec> currentTopVector; currentTopVector.reserve(nfaces); for(int j = 1; j < levels; j++) { // theta coordinate float t = static_cast<float>(j) * faceAngularHeight; for(int i = 0; i < nfaces; i++) { // phi coordinate float p = static_cast<float>(i) * faceAngularLength; currentTopVector.push_back(GsVec((rt * std::cos(p)) * std::cos(t), hlen + (rt * std::sin(t)), (rt * std::sin(p)) * std::cos(t))); } pushLevel(P, C, currentTopVector, previousTopVector, nfaces); std::swap(currentTopVector, previousTopVector); currentTopVector.clear(); } // Compute the cap of the capsule GsVec tv(0.0f, hlen + rt, 0.0f); for(int i = 0; i < nfaces; i++) { GsVec a = previousTopVector[i]; GsVec b = (i+1 == nfaces) ? previousTopVector[0] : previousTopVector[i+1]; pushTriangle(P, C, {a, b, tv}); } // Compute the bottom of the capsule std::vector<GsVec>& previousBottomVector = bodyBottomCoordinates; std::vector<GsVec> currentBottomVector; currentBottomVector.reserve(nfaces); for(int j = 1; j < levels; j++) { // theta coordinate float t = static_cast<float>(j) * faceAngularHeight; for(int i = 0; i < nfaces; i++) { // phi coordinate float p = static_cast<float>(i) * faceAngularLength; currentBottomVector.push_back(GsVec((rb * std::cos(p)) * std::cos(t), -hlen - (rb * std::sin(t)), (rb * std::sin(p)) * std::cos(t))); } pushLevel(P, C, currentBottomVector, previousBottomVector, nfaces); std::swap(currentBottomVector, previousBottomVector); currentBottomVector.clear(); } // Compute the cap of the capsule GsVec bv(0.0f, -hlen - rb, 0.0f); for(int i = 0; i < nfaces; i++) { GsVec a = previousBottomVector[i]; GsVec b = (i+1 == nfaces) ? previousBottomVector[0] : previousBottomVector[i+1]; pushTriangle(P, C, {a, bv, b}); } //pushCap(P, C, previousBottomVector, bv, nfaces); // send data to OpenGL buffers: glBindBuffer ( GL_ARRAY_BUFFER, buf[0] ); glBufferData ( GL_ARRAY_BUFFER, P.size()*3*sizeof(float), &P[0], GL_STATIC_DRAW ); glBindBuffer ( GL_ARRAY_BUFFER, buf[1] ); glBufferData ( GL_ARRAY_BUFFER, C.size()*4*sizeof(gsbyte), &C[0], GL_STATIC_DRAW ); // save size so that we can free our buffers and later just draw the OpenGL arrays: _numpoints = P.size(); // free non-needed memory: P.resize(0); C.resize(0); changed = 0; }
// fill your arrays here, may be called each time the object has to change: void SoTriangles::build ( float x, float y, float z, GLuint *textures) { // start by filling your data in arrays: // P.push().set ( .. ); // ... P.size(0); N.size(0); T.size(0); P.push(GsVec(-x, y, -z)); N.push(GsVec(0, 1, 0)); T.push(GsVec2(0.0f, 0.0f)); P.push(GsVec(-x, y, z)); N.push(GsVec(0, 1, 0)); T.push(GsVec2(0.0f, 1.0f)); P.push(GsVec(x, y, z)); N.push(GsVec(0, 1, 0)); T.push(GsVec2(1.0f, 1.0f)); P.push(GsVec(x, y, -z)); N.push(GsVec(0, 1, 0)); T.push(GsVec2(1.0f, 0.0f)); P.push(GsVec(-x, y, -z)); N.push(GsVec(0, 1, 0)); T.push(GsVec2(0.0f, 0.0f)); P.push(GsVec(x, y, z)); N.push(GsVec(0, 1, 0)); T.push(GsVec2(1.0f, 1.0f)); // then send data to OpenGL buffers: glBindVertexArray ( va[0] ); glBindTexture(GL_TEXTURE_2D, textures[0]); glEnableVertexAttribArray ( 0 ); // for each buffer there will be one vertex atribute glEnableVertexAttribArray ( 1 ); glEnableVertexAttribArray(2); glBindBuffer ( GL_ARRAY_BUFFER, buf[0] ); glBufferData ( GL_ARRAY_BUFFER, 3*sizeof(float)*P.size(), P.pt(), GL_STATIC_DRAW ); glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, 0 ); // tell what glBindBuffer(GL_ARRAY_BUFFER, buf[1]); glBufferData(GL_ARRAY_BUFFER, N.size() * 3 * sizeof(float), &N[0], GL_STATIC_DRAW); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ARRAY_BUFFER, buf[2]); // texture glBufferData(GL_ARRAY_BUFFER, T.size() * 2 * sizeof(float), &T[0], GL_STATIC_DRAW); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0); // false means no normalization //glBindBuffer ( GL_ARRAY_BUFFER, buf[1] ); // etc glBindVertexArray(0); // break the existing vertex array object binding. // save size so that we can free our buffers and later draw the OpenGL arrays: _numelements = P.size(); // free non-needed memory: P.capacity(0); N.capacity(0); T.capacity(0); }
// here we will redraw the scene according to the current state of the application. void AppWindow::glutDisplay () { // Clear the rendering window glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // Build a cross with some lines (if not built yet): if ( _axis.changed ) // needs update { _axis.build(1.0f); // axis has radius 1.0 } if (sunanim) { sunx = 2 * (cos(2 * M_PI*sunxc / 360) + sin(2 * M_PI*sunxc / 360)); suny = 20.0f; sunz = 2 * (-sin(2 * M_PI*sunxz / 360) + cos(2 * M_PI*sunxz / 360)); } else { sunx = 0.0; suny = 1; sunz = -.5; } // Define our scene transformation: GsMat rx, ry, stransf, barrelroll, leftright, transf, updown, rightwing, leftwing, offsety, centerrwing, centerlwing, rl, rr, backR, backL, centerbackl, centerbackr, br, bl; GsMat rfrot, lfrot, rbrot, lbrot, rollyawpitch, ShadowT; rx.rotx ( _rotx ); ry.roty ( _roty ); stransf = rx*ry; // set the scene transformation matrix offsety.translation(GsVec(0.0f, -5.7f, 0.0f)); //Rotate many degrees barrelroll.rotz(2 * M_PI * rotate / 360); leftright.roty(2 * M_PI * _turnlr / 360); updown.rotx(2 * M_PI * _turnud / 360); rollyawpitch = leftright*updown*barrelroll; //Translate front wings to center centerrwing.translation(GsVec(-0.1f,-0.15f,0.0f)); centerlwing.translation(GsVec(0.1f, -0.15f, 0.0f)); //Translate front wings back to airplane rr.translation(GsVec(0.1f, 0.15f, 0.0f)); rl.translation(GsVec(-0.1f, 0.15f, 0.0f)); //Translate back wings to center centerbackl.translation(GsVec(-0.05f, -0.2f, 0.0f)); centerbackr.translation(GsVec(0.05f, -0.2f, 0.0f)); //Translate back wings to airplane bl.translation(GsVec(0.05f, 0.2f, 0.0f)); br.translation(GsVec(-0.05f, 0.2f, 0.0f)); //Rotate front wings rightwing.rotz(2 * M_PI * _wingsflyR / 360); leftwing.rotz(2 * M_PI * -_wingsflyL / 360); //Rotate back wings backR.rotz(2 * M_PI * _backR / 360); backL.rotz(2 * M_PI * -_backL / 360); //Clean up draw function rfrot = rr*rightwing*centerrwing; lfrot = rl*leftwing*centerlwing; rbrot = br*backR*centerbackr; lbrot = bl*backL*centerbackl; //speed is fast GsVec P = GsVec(0.0f, 0.0f, speed); GsVec bd = leftright*updown*barrelroll*P; R = R + bd; transf.setrans(R); GsVec sbd = leftright*P; SR = SR + sbd; ShadowT.setrans(SR); // Define our projection transformation: // (see demo program in gltutors-projection.7z, we are replicating the same behavior here) GsMat camview, camview2, _birdseye, persp, sproj; GsVec eye(0,0,0), center(0,0,0), up(0,1,0); GsVec eye2(0, 10, 0), center2(0, 0, 0), up2(0, 0, 1); eye += R + leftright*updown*barrelroll*GsVec(0,0,2); center += R + GsVec(0, 0, 0); _sun.build(1.0f, sunx, suny, sunz); float ground[4] = { 0, 1, 0, 4.99 }; float light[4] = { sunx, suny, sunz, 0 }; float dot; GsMat shadowMat; dot = ground[0] * light[0] + ground[1] * light[1] + ground[2] * light[2] + ground[3] * light[3]; shadowMat.setl1(dot - light[0] * ground[0], 0.0 - light[0] * ground[1], 0.0 - light[0] * ground[2], 0.0 - light[0] * ground[3]); shadowMat.setl2(0.0 - light[1] * ground[0], dot - light[1] * ground[1], 0.0 - light[1] * ground[2], 0.0 - light[1] * ground[3]); shadowMat.setl3(0.0 - light[2] * ground[0], 0.0 - light[2] * ground[1], dot - light[2] * ground[2], 0.0 - light[2] * ground[3]); shadowMat.setl4(0.0 - light[3] * ground[0], 0.0 - light[3] * ground[1], 0.0 - light[3] * ground[2], dot - light[3] * ground[3]); //shadowMat = shadowMat*ry*rx; camview.lookat ( eye, center, up ); // set our 4x4 "camera" matrix camview2.lookat(eye2, center2, up2); float aspect=1.0f, znear=0.1f, zfar=5000.0f; persp.perspective ( _fovy, aspect, znear, zfar ); // set our 4x4 perspective matrix // Our matrices are in "line-major" format, so vertices should be multiplied on the // right side of a matrix multiplication, therefore in the expression below camview will // affect the vertex before persp, because v' = (persp*camview)*v = (persp)*(camview*v). if (camera) { sproj = persp * camview; // set final scene projection } else { sproj = persp * camview2; } // Note however that when the shader receives a matrix it will store it in column-major // format, what will cause our values to be transposed, and we will then have in our // shaders vectors on the left side of a multiplication to a matrix. float col = 1; // Draw: //if ( _viewaxis ) _axis.draw ( stransf, sproj ); _model.draw(stransf*transf*rollyawpitch, sproj, _light, 0); _model2.draw(stransf*transf*rollyawpitch*rfrot, sproj, _light, 0); _model3.draw(stransf*transf*rollyawpitch*lfrot, sproj, _light, 0); _model4.draw(stransf*transf*rollyawpitch, sproj, _light, 0); _model5.draw(stransf*transf*rollyawpitch*rbrot, sproj, _light, 0); _model6.draw(stransf*transf*rollyawpitch*lbrot, sproj, _light, 0); _floor.draw(stransf, sproj, _light, textures); _city.draw(stransf*offsety, sproj, _light, 0); _city.draw(stransf*shadowMat*offsety, sproj, _shadow, 0); //Shadow _model.draw(stransf*ShadowT*shadowMat*rollyawpitch, sproj, _shadow, 1); _model2.draw(stransf*ShadowT*shadowMat*rollyawpitch, sproj, _shadow, 1); _model3.draw(stransf*ShadowT*shadowMat*rollyawpitch, sproj, _shadow, 1); _model4.draw(stransf*ShadowT*shadowMat*rollyawpitch, sproj, _shadow, 1); _model5.draw(stransf*ShadowT*shadowMat*rollyawpitch, sproj, _shadow, 1); _model6.draw(stransf*ShadowT*shadowMat*rollyawpitch, sproj, _shadow, 1); _side.draw(stransf, sproj, _light, col, textures); _sun.draw(stransf, sproj); // Swap buffers and draw: glFlush(); // flush the pipeline (usually not necessary) glutSwapBuffers(); // we were drawing to the back buffer, now bring it to the front }
void SoCapsule::build(float r, float sunx, float suny, float sunz) { P.clear(); C.clear(); // set size to zero, just in case //P.reserve(18); C.reserve(18); // reserve space to avoid re-allocations from the calls below //sphere int nfaces = 20; double rt = 5; double rb = 5; double len = 0; double pi = 3.14159265358979323846; for (int i = 0; i < nfaces; i++) //for sphere { for (int j = 0; j < nfaces; j++) { P.push_back(GsVec(rt*cos(j * 2 * pi / nfaces)*cos(i*pi / (2 * nfaces)) + sunx, rt*sin(i*pi / (2 * nfaces)) + len + suny, rt*sin(j * 2 * pi / nfaces)*cos(i*pi / (2 * nfaces)) + sunz)); P.push_back(GsVec(rt*cos((j + 1) * 2 * pi / nfaces)*cos((i)*pi / (2 * nfaces)) + sunx, rt*sin((i)*pi / (2 * nfaces)) + len + suny, rt*sin((j + 1) * 2 * pi / nfaces)*cos((i)*pi / (2 * nfaces)) + sunz)); P.push_back(GsVec(rt*cos((j)* 2 * pi / nfaces)*cos((i + 1)*pi / (2 * nfaces)) + sunx, rt*sin((i + 1)*pi / (2 * nfaces)) + len + suny, rt*sin((j)* 2 * pi / nfaces)*cos((i + 1)*pi / (2 * nfaces)) + sunz)); C.push_back(GsColor::orange); C.push_back(GsColor::orange); C.push_back(GsColor::orange); P.push_back(GsVec(rt*cos((j)* 2 * pi / nfaces)*cos((i + 1)*pi / (2 * nfaces)) + sunx, rt*sin((i + 1)*pi / (2 * nfaces)) + len + suny, rt*sin((j)* 2 * pi / nfaces)*cos((i + 1)*pi / (2 * nfaces)) + sunz)); P.push_back(GsVec(rt*cos((j + 1) * 2 * pi / nfaces)*cos((i)*pi / (2 * nfaces)) + sunx, rt*sin((i)*pi / (2 * nfaces)) + len + suny, rt*sin((j + 1) * 2 * pi / nfaces)*cos((i)*pi / (2 * nfaces)) + sunz)); P.push_back(GsVec(rt*cos((j+1)* 2 * pi / nfaces)*cos((i + 1)*pi / (2 * nfaces)) + sunx, rt*sin((i + 1)*pi / (2 * nfaces)) + len + suny, rt*sin((j+1)* 2 * pi / nfaces)*cos((i + 1)*pi / (2 * nfaces)) + sunz)); C.push_back(GsColor::orange); C.push_back(GsColor::orange); C.push_back(GsColor::orange); P.push_back(GsVec(rb*cos(j * 2 * pi / nfaces)*cos(i*pi / (2 * nfaces)) + sunx, -1 * rb*sin(i*pi / (2 * nfaces)) - len + suny, rb*sin(j * 2 * pi / nfaces)*cos(i*pi / (2 * nfaces)) + sunz)); P.push_back(GsVec(rb*cos((j + 1) * 2 * pi / nfaces)*cos((i)*pi / (2 * nfaces)) + sunx, -1 * rb*sin((i)*pi / (2 * nfaces)) - len + suny, rb*sin((j + 1) * 2 * pi / nfaces)*cos((i)*pi / (2 * nfaces)) + sunz)); P.push_back(GsVec(rb*cos((j)* 2 * pi / nfaces)*cos((i + 1)*pi / (2 * nfaces)) + sunx, -1 * rb*sin((i + 1)*pi / (2 * nfaces)) - len + suny, rb*sin((j)* 2 * pi / nfaces)*cos((i + 1)*pi / (2 * nfaces)) + sunz)); C.push_back(GsColor::orange); C.push_back(GsColor::orange); C.push_back(GsColor::orange); P.push_back(GsVec(rb*cos((j)* 2 * pi / nfaces)*cos((i + 1)*pi / (2 * nfaces)) + sunx, -1 * rb*sin((i + 1)*pi / (2 * nfaces)) - len + suny, rb*sin((j)* 2 * pi / nfaces)*cos((i + 1)*pi / (2 * nfaces)) + sunz)); P.push_back(GsVec(rb*cos((j + 1) * 2 * pi / nfaces)*cos((i)*pi / (2 * nfaces)) + sunx, -1 * rb*sin((i)*pi / (2 * nfaces)) - len + suny, rb*sin((j + 1) * 2 * pi / nfaces)*cos((i)*pi / (2 * nfaces)) + sunz)); P.push_back(GsVec(rb*cos((j+1)* 2 * pi / nfaces)*cos((i + 1)*pi / (2 * nfaces)) + sunx, -1 * rb*sin((i + 1)*pi / (2 * nfaces)) - len + suny, rb*sin((j+1)* 2 * pi / nfaces)*cos((i + 1)*pi / (2 * nfaces)) + sunz)); C.push_back(GsColor::orange); C.push_back(GsColor::orange); C.push_back(GsColor::orange); } } // send data to OpenGL buffers: glBindBuffer(GL_ARRAY_BUFFER, buf[0]); glBufferData(GL_ARRAY_BUFFER, P.size() * 3 * sizeof(float), &P[0], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, buf[1]); glBufferData(GL_ARRAY_BUFFER, C.size() * 4 * sizeof(gsbyte), &C[0], GL_STATIC_DRAW); // save size so that we can free our buffers and later just draw the OpenGL arrays: _numpoints = P.size(); // free non-needed memory: P.resize(0); C.resize(0); }
void SoAxis::build ( float r ) { int i; const float d=r/20.0f; P.clear(); C.clear(); // set size to zero, just in case P.reserve(18); C.reserve(18); // reserve space to avoid re-allocations from the calls below P.push_back( GsVec( -r, 0, 0 ) ); P.push_back( GsVec( r, 0, 0 ) ); P.push_back( GsVec( r-d,-d, 0 ) ); P.push_back( GsVec( r, 0, 0 ) ); P.push_back( GsVec( r-d, d, 0 ) ); P.push_back( GsVec( r, 0, 0 ) ); for ( i=0; i<6; i++ ) C.push_back( GsColor::red ); // recall that GsColor has r,g,b,a values P.push_back( GsVec( 0, -r, 0 ) ); P.push_back( GsVec( 0, r, 0 ) ); P.push_back( GsVec( 0, r-d,-d ) ); P.push_back( GsVec( 0, r, 0 ) ); P.push_back( GsVec( 0, r-d, d ) ); P.push_back( GsVec( 0, r, 0 ) ); for ( i=0; i<6; i++ ) C.push_back( GsColor::green ); glColor3f ( 0, 0, 1 ); P.push_back( GsVec( 0, 0, -r ) ); P.push_back( GsVec( 0, 0, r ) ); P.push_back( GsVec( 0,-d, r-d ) ); P.push_back( GsVec( 0, 0, r ) ); P.push_back( GsVec( 0, d, r-d ) ); P.push_back( GsVec( 0, 0, r ) ); for ( i=0; i<6; i++ ) C.push_back( GsColor::blue ); // send data to OpenGL buffers: glBindBuffer ( GL_ARRAY_BUFFER, buf[0] ); glBufferData ( GL_ARRAY_BUFFER, P.size()*3*sizeof(float), &P[0], GL_STATIC_DRAW ); glBindBuffer ( GL_ARRAY_BUFFER, buf[1] ); glBufferData ( GL_ARRAY_BUFFER, C.size()*4*sizeof(gsbyte), &C[0], GL_STATIC_DRAW ); // save size so that we can free our buffers and later just draw the OpenGL arrays: _numpoints = P.size(); // free non-needed memory: P.resize(0); C.resize(0); }