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 */






