23At the lowest level of processing we manipulate bits in th
2.3At the lowest level of processing, we manipulate bits in the framebuffer. In WebGL, we can create a virtual framebuffer in our application as a two- dimensional array. You can experiment with simple raster algorithms, such as drawing lines or circles, through a function that generates a single value in the array. Write a small library that will allow you to work in a virtual frame- buffer that you create in memory. The core functions should be WritePixel and ReadPixel. Your library should allow you to set up and display your vir- tual framebuffer and to run a user program that reads and writes pixels using gl.POINTS in gl.drawArrays. 2.4 Turtle graphics is an alternative positioning system that is based on the concept of a turtle moving around the screen with a pen attached to the bottom of its shell. The turtle’s position can be described by a triplet (x, y, ), giving the location of the center and the orientation of the turtle. A typical API for such a system includes functions such as the following: init(x,y,theta); // initialize position and orientation of turtle forward(distance); right(angle); left(angle); pen(up_down); Implement a turtle graphics library using WebGL.
Solution
//2.4 program
turtle.cpp
 #include \"turtle.hpp\"
 #include <math.h>
GLfloat c = M_PI/180.0;
 void Turtle::init(double x, double y, double theta) {
     m_startx = x;
     m_starty = y;
     m_theta = theta;
 }
void Turtle::forward(double distance) {
     if (m_drawing) {
 //        glClear(GL_COLOR_BUFFER_BIT);
         glBegin(GL_LINES);
         glVertex2f(m_startx, m_starty);
         glVertex2f(m_startx+distance*cos(m_theta), m_starty+distance*sin(m_theta));
         glEnd();
         glFlush();
     }
   
     m_startx+= distance*cos(m_theta);
     m_starty+= distance*sin(m_theta);
 }
void Turtle::right(double angle) {
     m_theta-=angle;
     if (m_theta < 0.0) {
         m_theta+=360.0;
     }
 }
void Turtle::left(double angle) {
     m_theta+=angle;
     if (m_theta > 360.0) {
         m_theta-=360.0;
     }
 }
void Turtle::pen(bool up_down) {
     if (up_down) {
         m_drawing = true;
     }
     else m_drawing = false;
 }
Turtle* tur = new Turtle();
 void display() {
     glClear(GL_COLOR_BUFFER_BIT);
     tur->init(0.0, 0.0, 0);
     tur->pen(true);
     tur->forward(50);
     tur->pen(false);
     tur->left(90*c);
     tur->forward(50);
     tur->pen(true);
     tur->right(75*c);
     tur->forward(50);
 }
void myReshape(int w, int h) {
     glViewport(0, 0, w, h);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     if (w <= h)
         glOrtho(-200.0, 200.0, -200.0*(GLfloat)h/(GLfloat)w, 200.0*(GLfloat)h/(GLfloat)w,-10.0, 10.0);
     else
         glOrtho(-200.0*(GLfloat)h/(GLfloat)w, 200.0*(GLfloat)h/(GLfloat)w, -200.0, 200.0, -10.0, 10.0);
     glMatrixMode(GL_MODELVIEW);
     glutPostRedisplay();
 }
int main(int argc, char ** argv) {
     glutInit(&argc, argv);
     glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
     glutInitWindowSize(500,500);
     glutInitWindowPosition(0, 0);
     glutCreateWindow(\"Xcode Glut Demo\");
     glutReshapeFunc(myReshape);
     glutDisplayFunc(display);
     glutMainLoop();
     glClearColor(1.0, 1.0, 1.0, 1.0);
     glColor3f(0.0,0.0,0.0);
     glClear(GL_COLOR_BUFFER_BIT);
   
 //    glMatrixMode(GL_PROJECTION);
 //    glLoadIdentity();
 //    gluOrtho2D(0.0, 50.0, 0.0, 50.0);
 //    glMatrixMode(GL_MODELVIEW);
    return 0;
   
 }
 turtle.hpp
 #ifndef turtle_hpp
 #define turtle_hpp
#include <stdio.h>
 #include <GLUT/GLUT.h>
class Turtle {
 public:
     Turtle(){};
     ~Turtle(){};
   
     void init(double x, double y, double theta);
     void forward(double distance);
     void right(double angle);
     void left(double angle);
     void pen(bool up_down);
 private:
     double m_startx = 0.0;
     double m_starty = 0.0;
     double m_theta = 0.0;
     bool m_drawing = false;
 };
 #endif /* turtle_hpp */
 //2.3 program
test.cpp
 #include \"test.hpp\"
 #include \"miniOpenglToolkit.hpp\"
 #include <GLUT/GLUT.h>
 #include <math.h>
 #include <iostream>
#define max(a, b) a>b?a:b
 GLint mWidth = 640;
 GLint mHeight = 640;
MiniOpenglToolkit* mot = new MiniOpenglToolkit();
inline void swap_int(int *a, int *b) {
     *a ^= *b;
     *b ^= *a;
     *a ^= *b;
 }
void drawLineWithEquation(int x0, int y0, int xEnd, int yEnd) {
     float m = (float)(yEnd-y0)/(xEnd-x0);
     float mr = 1/m;
     if (m <= 1) {
         for (int x = x0; x <= xEnd; ++x) {
             int y = lroundf((x-x0)*m+y0);
             mot->writePixel(x, y);
         }
     }
     else {
         for (int y = y0; y <= yEnd; ++y) {
             int x = lroundf((y-y0)*mr+x0);
             mot->writePixel(x, y);
         }
     }
 }
void drawLineWithDDA(int x0, int y0, int xEnd, int yEnd) {
     int dx = xEnd-x0;
     int dy = yEnd-y0;
     float x = x0;
     float y = y0;
     int steps = max(std::abs(dx), std::abs(dy));
   
     float xIncrement = (float)(dx)/steps;
     float yIncrement = (float)(dy)/steps;
   
     mot->writePixel(x, y);
   
     for (int i = 0; i <= steps; ++i) {
         x += xIncrement;
         y += yIncrement;
         mot->writePixel(lroundf(x), lroundf(y));
     }
 }
void drawLineWithBresenham(int x0, int y0, int xEnd, int yEnd) {
     int dx = abs(xEnd-x0),
         dy = abs(yEnd-y0),
         yy = 0;
     if (dx < dy) {
         yy = 1;
         swap_int(&x0, &y0);
         swap_int(&xEnd, &yEnd);
         swap_int(&dx, &dy);
     }
   
     int ix = (xEnd-x0)>0?1:-1,
         iy = (yEnd-y0)>0?1:-1,
         cx = x0,
         cy = y0,
         n2dy = dy*2,
         n2dydx = (dy-dx)*2,
         d = dy*2-dx;
     if (yy) {
         while(cx != xEnd) {
             if (d < 0) {
                 d += n2dy;
             } else {
                 cy+=iy;
                 d += n2dydx;
             }
             mot->writePixel(cy, cx);
             cx += ix;
         }
     }else { //x45
         while(cx != xEnd) {
             if (d < 0) {
                 d += n2dy;
             } else {
                 cy += iy;
                 d += n2dydx;
             }
             mot->writePixel(cx, cy);
             cx += ix;
         }
     }
 }
 void _draw_circle_8(int xc, int yc, int x, int y) {
     mot->writePixel(xc+x, yc+y);
     mot->writePixel(xc-x, yc+y);
     mot->writePixel(xc+x, yc-y);
     mot->writePixel(xc-x, yc-y);
     mot->writePixel(xc+y, yc+x);
     mot->writePixel(xc-y, yc+x);
     mot->writePixel(xc+y, yc-x);
     mot->writePixel(xc-y, yc-x);
 }
 void drawCircleWithBresenham(int xc, int yc, int r, int fill) {
   
   
     if (xc + r < 0 || xc -r >= mWidth || yc + r < 0 || yc - r >= mHeight) return;
   
     int x = 0, y = r, yi, d;
     d = 3-2*r;
   
     if (fill) {
         while(x <= y) {
             for (yi = x; yi <= y; yi++) {
                 _draw_circle_8(xc, yc, x, yi);
             }
           
             if (d < 0) {
                 d = d+4*x+6;
             } else {
                 d = d+4*(x-y)+10;
                 y--;
             }
             x++;
         }
     } else {
         while(x <= y) {
             _draw_circle_8(xc, yc, x, y);
             if (d < 0) {
                 d = d+4*x+6;
             } else {
                 d = d+4*(x-y)+10;
                 y--;
             }
             x++;
         }
     }
 }
void display() {
     mot->clear();
 //    drawLineWithEquation(0, 0, 300, 50);
 //    drawLineWithEquation(0, 0, 300, 100);
 //    drawLineWithEquation(0, 0, 300, 150);
 //    drawLineWithEquation(0, 0, 300, 300);
 //    drawLineWithEquation(0, 0, 150, 300);
 //    drawLineWithEquation(0, 0, 100, 300);
 //    drawLineWithEquation(0, 0, 50, 300);
 //    drawLineWithEquation(300,0,300,50);
 //    drawLineWithDDA(0,0,0,300);
     drawLineWithBresenham(0, 0, 0, 300);
     drawCircleWithBresenham(0, 0, 300, 0);
   
   
     mot->flush();
 }
int main(int argc, char ** argv) {
     mot->init(argc, argv);
     mot->readPixel(mWidth,mHeight);
     mot->displayFunc(display);
     mot->mainLoop();
     return 0;
   
 }
 test.hpp
#ifndef test_hpp
 #define test_hpp
#include <stdio.h>
#endif /* test_hpp */
 miniOpenglToolkit.cpp
#include \"miniOpenglToolkit.hpp\"
void MiniOpenglToolkit::init(int argc, char ** argv) {
     glutInit(&argc, argv);
 }
MiniOpenglToolkit::MiniOpenglToolkit():defaultWidth(1),defaultHeight(1),defaultFormat(GL_BLUE),defaultType(GL_UNSIGNED_BYTE),defaultPixels(nullptr){}
void MiniOpenglToolkit::readPixel(GLint width, GLint height) {
     glutInitWindowSize(width, height);
     glutInitWindowPosition(200, 200);
     glutCreateWindow(\"Draw Line\");
     glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
     glClearColor(1.0,1.0,1.0,1.0);
     glColor3f(0.0, 0.0,0.0);
   
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     gluOrtho2D(-width/2, width/2, -height/2, height/2);
     glMatrixMode(GL_MODELVIEW);
     glEnableClientState(GL_VERTEX_ARRAY);
 }
void MiniOpenglToolkit::writePixel(GLint x, GLint y) {
     glBegin(GL_POINTS);
     GLint vertices[] = {x,y};
     glVertex2iv(vertices);
     glEnd();
 }
GLvoid* MiniOpenglToolkit::getPixels() {
     return this->defaultPixels;
 }
void MiniOpenglToolkit::mainLoop() {
     glutMainLoop();
 }
void MiniOpenglToolkit::displayFunc(void (*func)()) {
     glutDisplayFunc(func);
 }
void MiniOpenglToolkit::reshape() {
     glutReshapeFunc([](int width, int height) {
         glMatrixMode(GL_PROJECTION);
         glLoadIdentity();
         gluOrtho2D(-width/2, width/2, 0, height);
         glMatrixMode(GL_MODELVIEW);
     });
 }
void MiniOpenglToolkit::flush() {
     glFlush();
 }
void MiniOpenglToolkit::clear() {
     glClear(GL_COLOR_BUFFER_BIT);
 }
 miniOpenglToolkit.hpp
 #ifndef miniOpenglToolkit_hpp
 #define miniOpenglToolkit_hpp
#include <stdio.h>
 #include <GLUT/GLUT.h>
class MiniOpenglToolkit
 {
 public:
   
     MiniOpenglToolkit();
     ~MiniOpenglToolkit(){};
     void readPixel(GLint width, GLint height);
   
     void writePixel(GLint x, GLint y);
   
     GLvoid* getPixels();
   
     void init(int argc, char ** argv);
   
     void mainLoop();
   
     void displayFunc(void (*func)(void));
   
     /**
      @brief reshape func
      */
     void reshape();
     /**
      @brief flush
      */
     void flush();
   
     /**
      @brief clear
      */
     void clear();
 private:
     GLsizei defaultWidth;
     GLsizei defaultHeight;
     GLenum defaultFormat;
     GLenum defaultType;
     GLvoid* defaultPixels;
 };
 #endif /* miniOpenglToolkit_hpp */







