OpenGL.Project2.Bezier Curve

這次的OpenGL的project是完成了Bezeir曲線的生成,主要是兩種方式。

第一種是不斷地遞歸生成一些點,去逼近。

第二種是應用de casterjau算法生成Bezier曲線。

上代碼了

// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <array>
#include <sstream>
#include <iostream>
#include <math.h>
// Include GLEW
#include <GL/glew.h>
// Include GLFW
#include <glfw3.h>
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
using namespace glm;
// Include AntTweakBar
#include <AntTweakBar.h>

#include <common/shader.hpp>
#include <common/controls.hpp>
#include <common/objloader.hpp>
#include <common/vboindexer.hpp>
using namespace std;

typedef struct Vertex {
	float XYZW[4];
	float RGBA[4];
	void SetCoords(float *coords) {
		XYZW[0] = coords[0];
		XYZW[1] = coords[1];
		XYZW[2] = coords[2];
		XYZW[3] = coords[3];
	}
	void SetColor(float *color) {
		RGBA[0] = color[0];
		RGBA[1] = color[1];
		RGBA[2] = color[2];
		RGBA[3] = color[3];
	}
};

// ATTN: USE POINT STRUCTS FOR EASIER COMPUTATIONS
typedef struct point {
	float x, y, z;
	point(const float x = 0, const float y = 0, const float z = 0) : x(x), y(y), z(z){};
	point(float *coords) : x(coords[0]), y(coords[1]), z(coords[2]){};
	point operator -(const point& a)const {
		return point(x - a.x, y - a.y, z - a.z);
	}
	point operator +(const point& a)const {
		return point(x + a.x, y + a.y, z + a.z);
	}
	point operator *(const float& a)const {
		return point(x*a, y*a, z*a);
	}
	point operator /(const float& a)const {
		return point(x / a, y / a, z / a);
	}
	float* toArray() {
		float array[] = { x, y, z, 1.0f };
		return array;
	}
};

// function prototypes
int initWindow(void);
void initOpenGL(void);
void createVAOs(Vertex[], unsigned short[], size_t, size_t, int);
void createObjects(void);
void pickVertex(void);
void moveVertex(void);
void drawScene(void);
void cleanup(void);
static void mouseCallback(GLFWwindow*, int, int, int);

// GLOBAL VARIABLES
GLFWwindow* window;
const GLuint window_width = 1024, window_height = 768;

glm::mat4 gProjectionMatrix;
glm::mat4 gViewMatrix;

GLuint gPickedIndex;
std::string gMessage;

GLuint programID;
GLuint pickingProgramID;

// ATTN: INCREASE THIS NUMBER AS YOU CREATE NEW OBJECTS
const GLuint NumObjects = 8;	// number of different "objects" to be drawn
GLuint VertexArrayId[NumObjects] = { 0,1,2,3,4,5,6,7 };
GLuint VertexBufferId[NumObjects] = { 0,1,2,3,4,5,6,7 };
GLuint IndexBufferId[NumObjects] = { 0,1,2,3,4,5,6,7 };
size_t NumVert[NumObjects] = { 0,1,2,3,4,5,6,7 };



GLuint MatrixID;
GLuint ViewMatrixID;
GLuint ModelMatrixID;
GLuint PickingMatrixID;
GLuint pickingColorArrayID;
GLuint pickingColorID;
GLuint LightID;

// Define objects
Vertex Vertices[] =
{
	{ { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
	{ { 0.7f, 0.7f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
	{ { 0.0f, 1.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
	{ { -0.7f, 0.7f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
	{ { -1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
	{ { -0.7f, -0.7f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
	{ { 0.0f, -1.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
	{ { 0.7f, -0.7f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
};
Vertex Vertices2[] = {
	{ { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
	{ { 0.7f, 0.7f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
	{ { 0.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
	{ { -0.7f, 0.7f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
	{ { -1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
	{ { -0.7f, -0.7f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
	{ { 0.0f, -1.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
	{ { 0.7f, -0.7f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
	{ { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
};
unsigned short Indices[] = {
	0, 1, 2, 3, 4, 5, 6, 7
};
Vertex Vertices3[16];
Vertex Vertices4[32];
Vertex Vertices5[64];
Vertex Vertices6[128];
Vertex Vertices7[32];
Vertex Vertices8[320];
unsigned short Indices2[] = {
	0, 1, 2, 3, 4, 5, 6, 7,8,9,10,11,12,13,14,15
};
unsigned short Indices3[] = {
	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
};
unsigned short Indices4[] = {
	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63
};
unsigned short Indices5[] = {
	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
	121, 122, 123, 124, 125, 126, 127
};
unsigned short Indices6[] = {
	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
};
unsigned short Indices7[] = {
	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
	66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
	124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
	175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225,
	226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276,
	277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319
};

Vertex sd[256];
Vertex sd2[256];

const size_t IndexCount = sizeof(Indices) / sizeof(unsigned short);
// ATTN: DON'T FORGET TO INCREASE THE ARRAY SIZE IN THE PICKING VERTEX SHADER WHEN YOU ADD MORE PICKING COLORS
float pickingColor[IndexCount] = { 0 / 255.0f, 1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f, 5 / 255.0f, 6 / 255.0f, 7 / 255.0f };
int cooot = 0; int cooot2 = 0;
// ATTN: ADD YOU PER-OBJECT GLOBAL ARRAY DEFINITIONS HERE
bool KeyLastFrame = GLFW_RELEASE;
bool KeyLastFrame2 = GLFW_RELEASE;
bool fm = true;
bool fm2 = true;
void createObjects(void)
{   //first level subdivision
	for (int i = 0; i < 8; i++){
		sd[i] = Vertices[i];
	}
		Vertex tmp = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } };
		Vertex tmp2 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } };
		float cord1[4]; float cord2[4]; cord1[2] = 0.0f; cord1[3] = 1.0f; cord2[2] = 0.0f; cord2[3] = 1.0f;
		cord1[0] = (sd[7].XYZW[0] + 10 * sd[0].XYZW[0] + 5 * sd[1].XYZW[0]) / 16;
		cord1[1] = (sd[7].XYZW[1] + 10 * sd[0].XYZW[1] + 5 * sd[1].XYZW[1]) / 16;
		cord2[0] = (5 * sd[0].XYZW[0] + 10 * sd[1].XYZW[0] + sd[2].XYZW[0]) / 16;
		cord2[1] = (5 * sd[0].XYZW[1] + 10 * sd[1].XYZW[1] + sd[2].XYZW[1]) / 16;
		tmp.SetCoords(cord1); tmp2.SetCoords(cord2);
		Vertices3[2] = tmp;
		Vertices3[3] = tmp2;
		cord1[0] = (sd[6].XYZW[0] + 10 * sd[7].XYZW[0] + 5 * sd[0].XYZW[0]) / 16;
		cord1[1] = (sd[6].XYZW[1] + 10 * sd[7].XYZW[1] + 5 * sd[0].XYZW[1]) / 16;
		cord2[0] = (5 * sd[7].XYZW[0] + 10 * sd[0].XYZW[0] + sd[1].XYZW[0]) / 16;
		cord2[1] = (5 * sd[7].XYZW[1] + 10 * sd[0].XYZW[1] + sd[1].XYZW[1]) / 16;
		tmp.SetCoords(cord1); tmp2.SetCoords(cord2);
		Vertices3[0] = tmp;
		Vertices3[1] = tmp2;
		cord1[0] = (sd[5].XYZW[0] + 10 * sd[6].XYZW[0] + 5 * sd[7].XYZW[0]) / 16;
		cord1[1] = (sd[5].XYZW[1] + 10 * sd[6].XYZW[1] + 5 * sd[7].XYZW[1]) / 16;
		cord2[0] = (5 * sd[6].XYZW[0] + 10 * sd[7].XYZW[0] + sd[0].XYZW[0]) / 16;
		cord2[1] = (5 * sd[6].XYZW[1] + 10 * sd[7].XYZW[1] + sd[0].XYZW[1]) / 16;
		tmp.SetCoords(cord1); tmp2.SetCoords(cord2);
		Vertices3[14] = tmp;
		Vertices3[15] = tmp2;
	for (int i = 2; i < 7; i++){
		Vertex tmp = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } };
		Vertex tmp2 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } };
		float cord1[4]; float cord2[4]; cord1[2] = 0.0f; cord1[3] = 1.0f; cord2[2] = 0.0f; cord2[3] = 1.0f;
		cord1[0] = (sd[i - 2].XYZW[0] + 10 * sd[i - 1].XYZW[0] + 5 * sd[i].XYZW[0])/16;
		cord1[1] = (sd[i - 2].XYZW[1] + 10 * sd[i - 1].XYZW[1] + 5 * sd[i].XYZW[1])/16;
		cord2[0] = (5*sd[i - 1].XYZW[0] + 10 * sd[i].XYZW[0] + sd[i+1].XYZW[0])/16;
		cord2[1] = (5*sd[i - 1].XYZW[1] + 10 * sd[i].XYZW[1] + sd[i+1].XYZW[1])/16;
		tmp.SetCoords(cord1); tmp2.SetCoords(cord2);
		Vertices3[2 * i] = tmp;
		Vertices3[2 * i + 1] = tmp2;
	}
	//Second level subdivision
	for (int i = 0; i < 16; i++){
		sd[i] = Vertices3[i];
	}
	 tmp = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } };
	 tmp2 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } };
	cord1[2] = 0.0f; cord1[3] = 1.0f; cord2[2] = 0.0f; cord2[3] = 1.0f;
	cord1[0] = (sd[15].XYZW[0] + 10 * sd[0].XYZW[0] + 5 * sd[1].XYZW[0]) / 16;
	cord1[1] = (sd[15].XYZW[1] + 10 * sd[0].XYZW[1] + 5 * sd[1].XYZW[1]) / 16;
	cord2[0] = (5 * sd[0].XYZW[0] + 10 * sd[1].XYZW[0] + sd[2].XYZW[0]) / 16;
	cord2[1] = (5 * sd[0].XYZW[1] + 10 * sd[1].XYZW[1] + sd[2].XYZW[1]) / 16;
	tmp.SetCoords(cord1); tmp2.SetCoords(cord2);
	Vertices4[2] = tmp;
	Vertices4[3] = tmp2;
	cord1[0] = (sd[14].XYZW[0] + 10 * sd[15].XYZW[0] + 5 * sd[0].XYZW[0]) / 16;
	cord1[1] = (sd[14].XYZW[1] + 10 * sd[15].XYZW[1] + 5 * sd[0].XYZW[1]) / 16;
	cord2[0] = (5 * sd[15].XYZW[0] + 10 * sd[0].XYZW[0] + sd[1].XYZW[0]) / 16;
	cord2[1] = (5 * sd[15].XYZW[1] + 10 * sd[0].XYZW[1] + sd[1].XYZW[1]) / 16;
	tmp.SetCoords(cord1); tmp2.SetCoords(cord2);
	Vertices4[0] = tmp;
	Vertices4[1] = tmp2;
	cord1[0] = (sd[13].XYZW[0] + 10 * sd[14].XYZW[0] + 5 * sd[15].XYZW[0]) / 16;
	cord1[1] = (sd[13].XYZW[1] + 10 * sd[14].XYZW[1] + 5 * sd[15].XYZW[1]) / 16;
	cord2[0] = (5 * sd[14].XYZW[0] + 10 * sd[15].XYZW[0] + sd[0].XYZW[0]) / 16;
	cord2[1] = (5 * sd[14].XYZW[1] + 10 * sd[15].XYZW[1] + sd[0].XYZW[1]) / 16;
	tmp.SetCoords(cord1); tmp2.SetCoords(cord2);
	Vertices4[30] = tmp;
	Vertices4[31] = tmp2;
	for (int i = 2; i < 15; i++){
		Vertex tmp = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } };
		Vertex tmp2 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } };
		float cord1[4]; float cord2[4]; cord1[2] = 0.0f; cord1[3] = 1.0f; cord2[2] = 0.0f; cord2[3] = 1.0f;
		cord1[0] = (sd[i - 2].XYZW[0] + 10 * sd[i - 1].XYZW[0] + 5 * sd[i].XYZW[0]) / 16;
		cord1[1] = (sd[i - 2].XYZW[1] + 10 * sd[i - 1].XYZW[1] + 5 * sd[i].XYZW[1]) / 16;
		cord2[0] = (5 * sd[i - 1].XYZW[0] + 10 * sd[i].XYZW[0] + sd[i + 1].XYZW[0]) / 16;
		cord2[1] = (5 * sd[i - 1].XYZW[1] + 10 * sd[i].XYZW[1] + sd[i + 1].XYZW[1]) / 16;
		tmp.SetCoords(cord1); tmp2.SetCoords(cord2);
		Vertices4[2 * i] = tmp;
		Vertices4[2 * i + 1] = tmp2;
	}
	//Third level subdivision
	for (int i = 0; i < 32; i++){
		sd[i] = Vertices4[i];
	}
	tmp = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } };
	tmp2 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } };
	cord1[2] = 0.0f; cord1[3] = 1.0f; cord2[2] = 0.0f; cord2[3] = 1.0f;
	cord1[0] = (sd[31].XYZW[0] + 10 * sd[0].XYZW[0] + 5 * sd[1].XYZW[0]) / 16;
	cord1[1] = (sd[31].XYZW[1] + 10 * sd[0].XYZW[1] + 5 * sd[1].XYZW[1]) / 16;
	cord2[0] = (5 * sd[0].XYZW[0] + 10 * sd[1].XYZW[0] + sd[2].XYZW[0]) / 16;
	cord2[1] = (5 * sd[0].XYZW[1] + 10 * sd[1].XYZW[1] + sd[2].XYZW[1]) / 16;
	tmp.SetCoords(cord1); tmp2.SetCoords(cord2);
	Vertices5[2] = tmp;
	Vertices5[3] = tmp2;
	cord1[0] = (sd[30].XYZW[0] + 10 * sd[31].XYZW[0] + 5 * sd[0].XYZW[0]) / 16;
	cord1[1] = (sd[30].XYZW[1] + 10 * sd[31].XYZW[1] + 5 * sd[0].XYZW[1]) / 16;
	cord2[0] = (5 * sd[31].XYZW[0] + 10 * sd[0].XYZW[0] + sd[1].XYZW[0]) / 16;
	cord2[1] = (5 * sd[31].XYZW[1] + 10 * sd[0].XYZW[1] + sd[1].XYZW[1]) / 16;
	tmp.SetCoords(cord1); tmp2.SetCoords(cord2);
	Vertices5[0] = tmp;
	Vertices5[1] = tmp2;
	cord1[0] = (sd[29].XYZW[0] + 10 * sd[30].XYZW[0] + 5 * sd[31].XYZW[0]) / 16;
	cord1[1] = (sd[29].XYZW[1] + 10 * sd[30].XYZW[1] + 5 * sd[31].XYZW[1]) / 16;
	cord2[0] = (5 * sd[30].XYZW[0] + 10 * sd[31].XYZW[0] + sd[0].XYZW[0]) / 16;
	cord2[1] = (5 * sd[30].XYZW[1] + 10 * sd[31].XYZW[1] + sd[0].XYZW[1]) / 16;
	tmp.SetCoords(cord1); tmp2.SetCoords(cord2);
	Vertices5[62] = tmp;
	Vertices5[63] = tmp2;
	for (int i = 2; i < 31; i++){
		Vertex tmp = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } };
		Vertex tmp2 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } };
		float cord1[4]; float cord2[4]; cord1[2] = 0.0f; cord1[3] = 1.0f; cord2[2] = 0.0f; cord2[3] = 1.0f;
		cord1[0] = (sd[i - 2].XYZW[0] + 10 * sd[i - 1].XYZW[0] + 5 * sd[i].XYZW[0]) / 16;
		cord1[1] = (sd[i - 2].XYZW[1] + 10 * sd[i - 1].XYZW[1] + 5 * sd[i].XYZW[1]) / 16;
		cord2[0] = (5 * sd[i - 1].XYZW[0] + 10 * sd[i].XYZW[0] + sd[i + 1].XYZW[0]) / 16;
		cord2[1] = (5 * sd[i - 1].XYZW[1] + 10 * sd[i].XYZW[1] + sd[i + 1].XYZW[1]) / 16;
		tmp.SetCoords(cord1); tmp2.SetCoords(cord2);
		Vertices5[2 * i] = tmp;
		Vertices5[2 * i + 1] = tmp2;
	}
	//Fifth level subdivision
	for (int i = 0; i < 64; i++){
		sd[i] = Vertices5[i];
	}
	tmp = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } };
	tmp2 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } };
	cord1[2] = 0.0f; cord1[3] = 1.0f; cord2[2] = 0.0f; cord2[3] = 1.0f;
	cord1[0] = (sd[63].XYZW[0] + 10 * sd[0].XYZW[0] + 5 * sd[1].XYZW[0]) / 16;
	cord1[1] = (sd[63].XYZW[1] + 10 * sd[0].XYZW[1] + 5 * sd[1].XYZW[1]) / 16;
	cord2[0] = (5 * sd[0].XYZW[0] + 10 * sd[1].XYZW[0] + sd[2].XYZW[0]) / 16;
	cord2[1] = (5 * sd[0].XYZW[1] + 10 * sd[1].XYZW[1] + sd[2].XYZW[1]) / 16;
	tmp.SetCoords(cord1); tmp2.SetCoords(cord2);
	Vertices6[2] = tmp;
	Vertices6[3] = tmp2;
	cord1[0] = (sd[62].XYZW[0] + 10 * sd[63].XYZW[0] + 5 * sd[0].XYZW[0]) / 16;
	cord1[1] = (sd[62].XYZW[1] + 10 * sd[63].XYZW[1] + 5 * sd[0].XYZW[1]) / 16;
	cord2[0] = (5 * sd[63].XYZW[0] + 10 * sd[0].XYZW[0] + sd[1].XYZW[0]) / 16;
	cord2[1] = (5 * sd[63].XYZW[1] + 10 * sd[0].XYZW[1] + sd[1].XYZW[1]) / 16;
	tmp.SetCoords(cord1); tmp2.SetCoords(cord2);
	Vertices6[0] = tmp;
	Vertices6[1] = tmp2;
	cord1[0] = (sd[61].XYZW[0] + 10 * sd[62].XYZW[0] + 5 * sd[63].XYZW[0]) / 16;
	cord1[1] = (sd[61].XYZW[1] + 10 * sd[62].XYZW[1] + 5 * sd[63].XYZW[1]) / 16;
	cord2[0] = (5 * sd[62].XYZW[0] + 10 * sd[63].XYZW[0] + sd[0].XYZW[0]) / 16;
	cord2[1] = (5 * sd[62].XYZW[1] + 10 * sd[63].XYZW[1] + sd[0].XYZW[1]) / 16;
	tmp.SetCoords(cord1); tmp2.SetCoords(cord2);
	Vertices6[126] = tmp;
	Vertices6[127] = tmp2;
	for (int i = 2; i < 63; i++){
		Vertex tmp = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } };
		Vertex tmp2 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } };
		float cord1[4]; float cord2[4]; cord1[2] = 0.0f; cord1[3] = 1.0f; cord2[2] = 0.0f; cord2[3] = 1.0f;
		cord1[0] = (sd[i - 2].XYZW[0] + 10 * sd[i - 1].XYZW[0] + 5 * sd[i].XYZW[0]) / 16;
		cord1[1] = (sd[i - 2].XYZW[1] + 10 * sd[i - 1].XYZW[1] + 5 * sd[i].XYZW[1]) / 16;
		cord2[0] = (5 * sd[i - 1].XYZW[0] + 10 * sd[i].XYZW[0] + sd[i + 1].XYZW[0]) / 16;
		cord2[1] = (5 * sd[i - 1].XYZW[1] + 10 * sd[i].XYZW[1] + sd[i + 1].XYZW[1]) / 16;
		tmp.SetCoords(cord1); tmp2.SetCoords(cord2);
		Vertices6[2 * i] = tmp;
		Vertices6[2 * i + 1] = tmp2;
	}
	//Setting C3 Bezier control points
	for (int i = 0; i < 8; i++){
		sd2[i] = Vertices[i];
	}
	tmp = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } };
	tmp2 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } };
	Vertex tmp3 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } };
	Vertex tmp4 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } };
    float cord3[4]; float cord4[4];
	cord1[2] = 0.0f; cord1[3] = 1.0f; cord2[2] = 0.0f; cord2[3] = 1.0f;
	cord3[2] = 0.0f; cord3[3] = 1.0f; cord4[2] = 0.0f; cord4[3] = 1.0f;
	cord1[0] = (sd2[6].XYZW[0] + 11 * sd2[7].XYZW[0] + 11 * sd2[0].XYZW[0] + sd2[1].XYZW[0]) / 24;
	cord1[1] = (sd2[6].XYZW[1] + 11 * sd2[7].XYZW[1] + 11 * sd2[0].XYZW[1] + sd2[1].XYZW[1]) / 24;
	cord2[0] = (8 * sd2[7].XYZW[0] + 14 * sd2[0].XYZW[0] + 2 * sd2[1].XYZW[0]) / 24;
	cord2[1] = (8 * sd2[7].XYZW[1] + 14 * sd2[0].XYZW[1] + 2 * sd2[1].XYZW[1]) / 24;
	cord3[0] = (4 * sd2[7].XYZW[0] + 16 * sd2[0].XYZW[0] + 4 * sd2[1].XYZW[0]) / 24;
	cord3[1] = (4 * sd2[7].XYZW[1] + 16 * sd2[0].XYZW[1] + 4 * sd2[1].XYZW[1]) / 24;
	cord4[0] = (2 * sd2[7].XYZW[0] + 14 * sd2[0].XYZW[0] + 8 * sd2[1].XYZW[0]) / 24;
	cord4[1] = (2 * sd2[7].XYZW[1] + 14 * sd2[0].XYZW[1] + 8 * sd2[1].XYZW[1]) / 24;
	tmp.SetCoords(cord1); tmp2.SetCoords(cord2); tmp3.SetCoords(cord3); tmp4.SetCoords(cord4);
	Vertices7[0] = tmp;
	Vertices7[1] = tmp2;
	Vertices7[2] = tmp3;
	Vertices7[3] = tmp4;
	tmp = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } };
	tmp2 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } };
    tmp3 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } };
	tmp4 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } };
	cord1[2] = 0.0f; cord1[3] = 1.0f; cord2[2] = 0.0f; cord2[3] = 1.0f;
	cord3[2] = 0.0f; cord3[3] = 1.0f; cord4[2] = 0.0f; cord4[3] = 1.0f;
	cord1[0] = (sd2[7].XYZW[0] + 11 * sd2[0].XYZW[0] + 11 * sd2[1].XYZW[0] + sd2[2].XYZW[0]) / 24;
	cord1[1] = (sd2[7].XYZW[1] + 11 * sd2[0].XYZW[1] + 11 * sd2[1].XYZW[1] + sd2[2].XYZW[1]) / 24;
	cord2[0] = (8 * sd2[0].XYZW[0] + 14 * sd2[1].XYZW[0] + 2 * sd2[2].XYZW[0]) / 24;
	cord2[1] = (8 * sd2[0].XYZW[1] + 14 * sd2[1].XYZW[1] + 2 * sd2[2].XYZW[1]) / 24;
	cord3[0] = (4 * sd2[0].XYZW[0] + 16 * sd2[1].XYZW[0] + 4 * sd2[2].XYZW[0]) / 24;
	cord3[1] = (4 * sd2[0].XYZW[1] + 16 * sd2[1].XYZW[1] + 4 * sd2[2].XYZW[1]) / 24;
	cord4[0] = (2 * sd2[0].XYZW[0] + 14 * sd2[1].XYZW[0] + 8 * sd2[2].XYZW[0]) / 24;
	cord4[1] = (2 * sd2[0].XYZW[1] + 14 * sd2[1].XYZW[1] + 8 * sd2[2].XYZW[1]) / 24;
	tmp.SetCoords(cord1); tmp2.SetCoords(cord2); tmp3.SetCoords(cord3); tmp4.SetCoords(cord4);
	Vertices7[4] = tmp;
	Vertices7[5] = tmp2;
	Vertices7[6] = tmp3;
	Vertices7[7] = tmp4;
	tmp = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } };
	tmp2 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } };
	tmp3 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } };
	tmp4 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } };
	cord1[2] = 0.0f; cord1[3] = 1.0f; cord2[2] = 0.0f; cord2[3] = 1.0f;
	cord3[2] = 0.0f; cord3[3] = 1.0f; cord4[2] = 0.0f; cord4[3] = 1.0f;
	cord1[0] = (sd2[5].XYZW[0] + 11 * sd2[6].XYZW[0] + 11 * sd2[7].XYZW[0] + sd2[0].XYZW[0]) / 24;
	cord1[1] = (sd2[5].XYZW[1] + 11 * sd2[6].XYZW[1] + 11 * sd2[7].XYZW[1] + sd2[0].XYZW[1]) / 24;
	cord2[0] = (8 * sd2[6].XYZW[0] + 14 * sd2[7].XYZW[0] + 2 * sd2[0].XYZW[0]) / 24;
	cord2[1] = (8 * sd2[6].XYZW[1] + 14 * sd2[7].XYZW[1] + 2 * sd2[0].XYZW[1]) / 24;
	cord3[0] = (4 * sd2[6].XYZW[0] + 16 * sd2[7].XYZW[0] + 4 * sd2[0].XYZW[0]) / 24;
	cord3[1] = (4 * sd2[6].XYZW[1] + 16 * sd2[7].XYZW[1] + 4 * sd2[0].XYZW[1]) / 24;
	cord4[0] = (2 * sd2[6].XYZW[0] + 14 * sd2[7].XYZW[0] + 8 * sd2[0].XYZW[0]) / 24;
	cord4[1] = (2 * sd2[6].XYZW[1] + 14 * sd2[7].XYZW[1] + 8 * sd2[0].XYZW[1]) / 24;
	tmp.SetCoords(cord1); tmp2.SetCoords(cord2); tmp3.SetCoords(cord3); tmp4.SetCoords(cord4);
	Vertices7[28] = tmp;
	Vertices7[29] = tmp2;
	Vertices7[30] = tmp3;
	Vertices7[31] = tmp4;
	for (int i = 2; i < 7; i++){
		Vertex tmp = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } };
		Vertex tmp2 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } };
		Vertex tmp3 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } };
		Vertex tmp4 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } };
		Vertex tmp5 = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } };
		float cord1[4]; float cord2[4]; float cord3[4]; float cord4[4];
		cord1[2] = 0.0f; cord1[3] = 1.0f; cord2[2] = 0.0f; cord2[3] = 1.0f;
		cord3[2] = 0.0f; cord3[3] = 1.0f; cord4[2] = 0.0f; cord4[3] = 1.0f;
		cord1[0] = (sd2[i - 2].XYZW[0] + 11 * sd2[i - 1].XYZW[0] + 11 * sd2[i].XYZW[0] + sd2[i + 1].XYZW[0]) / 24;
		cord1[1] = (sd2[i - 2].XYZW[1] + 11 * sd2[i - 1].XYZW[1] + 11 * sd2[i].XYZW[1] + sd2[i + 1].XYZW[1]) / 24;
		cord2[0] = (8 * sd2[i - 1].XYZW[0] + 14 * sd2[i].XYZW[0] + 2*sd2[i + 1].XYZW[0]) / 24;
		cord2[1] = (8 * sd2[i - 1].XYZW[1] + 14 * sd2[i].XYZW[1] + 2 * sd2[i + 1].XYZW[1]) / 24;
		cord3[0] = (4 * sd2[i - 1].XYZW[0] + 16 * sd2[i].XYZW[0] + 4 * sd2[i + 1].XYZW[0]) / 24;
		cord3[1] = (4 * sd2[i - 1].XYZW[1] + 16 * sd2[i].XYZW[1] + 4 * sd2[i + 1].XYZW[1]) / 24;
		cord4[0] = (2 * sd2[i - 1].XYZW[0] + 14 * sd2[i].XYZW[0] + 8 * sd2[i + 1].XYZW[0]) / 24;
		cord4[1] = (2 * sd2[i - 1].XYZW[1] + 14 * sd2[i].XYZW[1] + 8 * sd2[i + 1].XYZW[1]) / 24;
		tmp.SetCoords(cord1); tmp2.SetCoords(cord2); tmp3.SetCoords(cord3); tmp4.SetCoords(cord4);
		Vertices7[4 * i] = tmp;
		Vertices7[4 * i + 1] = tmp2;
		Vertices7[4 * i + 2] = tmp3;
		Vertices7[4 * i + 3] = tmp4;

	}
	//Bezier Curve by De Casterjau's algorithm
	for (int i = 0; i < 32; i++){
		sd2[i] = Vertices7[i];
	}
	cord1[2] = 0.0f; cord1[3] = 1.0f;
	float t = 0; int x;
	while (t < 1){
		float m4 = pow(t, 4.0); float n4 = pow((1 - t), 4.0);
		float m3 = pow(t, 3.0); float n3 = pow((1 - t), 3.0);
		float m2 = pow(t, 2.0); float n2 = pow((1 - t), 2.0);
		float m1 = pow(t, 1.0); float n1 = pow((1 - t), 1.0);
		Vertex tmp = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 0.0f, 1.0f } };
		cord1[0] = n4*sd2[28].XYZW[0] + 4 * n3*m1 * sd2[29].XYZW[0] + 6 * m2*n2 * sd2[30].XYZW[0] + 4 * m3*n1*sd2[31].XYZW[0] + m4*sd2[0].XYZW[0];
		cord1[1] = n4*sd2[28].XYZW[1] + 4 * n3*m1 * sd2[29].XYZW[1] + 6 * m2*n2 * sd2[30].XYZW[1] + 4 * m3*n1*sd2[31].XYZW[1] + m4*sd2[0].XYZW[1];
		tmp.SetCoords(cord1);
		x = 40 * t;
		Vertices8[7 * 40 + x] = tmp;
		t += 0.025;
	}
	for (int i = 2; i < 28; i+=4){
		float t = 0;
		while (t < 1){
			int q = i/4;
			float m4 = pow(t, 4.0); float n4 = pow((1 - t), 4.0);
			float m3 = pow(t, 3.0); float n3 = pow((1 - t), 3.0);
			float m2 = pow(t, 2.0); float n2 = pow((1 - t), 2.0);
			float m1 = pow(t, 1.0); float n1 = pow((1 - t), 1.0);
			Vertex tmp = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 0.0f, 1.0f } };
			cord1[0] = n4*sd2[i - 2].XYZW[0] + 4 * n3*m1 * sd2[i - 1].XYZW[0] + 6 * m2*n2 * sd2[i].XYZW[0] + 4 * m3*n1*sd2[i + 1].XYZW[0] + m4*sd2[i + 2].XYZW[0];
			cord1[1] = n4*sd2[i - 2].XYZW[1] + 4 * n3*m1 * sd2[i - 1].XYZW[1] + 6 * m2*n2 * sd2[i].XYZW[1] + 4 * m3*n1*sd2[i + 1].XYZW[1] + m4*sd2[i + 2].XYZW[1];
			tmp.SetCoords(cord1);
			x = 40 * t;
			Vertices8[40*q+x] = tmp;
			t += 0.025;
		}
	}




	// ATTN: DERIVE YOUR NEW OBJECTS HERE:
	// each has one vertices {pos;color} and one indices array (no picking needed here)

}

void drawScene(void)
{
	// Dark blue background
	glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
	// Re-clear the screen for real rendering
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glUseProgram(programID);
	{
		glm::mat4 ModelMatrix = glm::mat4(1.0); // TranslationMatrix * RotationMatrix;
		glm::mat4 MVP = gProjectionMatrix * gViewMatrix * ModelMatrix;

		// Send our transformation to the currently bound shader,
		// in the "MVP" uniform
		glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
		glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &ModelMatrix[0][0]);
		glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &gViewMatrix[0][0]);
		glm::vec3 lightPos = glm::vec3(4, 4, 4);
		glUniform3f(LightID, lightPos.x, lightPos.y, lightPos.z);

		glEnable(GL_PROGRAM_POINT_SIZE);

		glBindVertexArray(VertexArrayId[0]);	// draw Vertices
			glBindBuffer(GL_ARRAY_BUFFER, VertexBufferId[0]);
			glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertices), Vertices);				// update buffer data
			//glDrawElements(GL_LINE_LOOP, NumVert[0], GL_UNSIGNED_SHORT, (void*)0);
			glDrawElements(GL_POINTS, NumVert[0], GL_UNSIGNED_SHORT, (void*)0);
			//glVertexPointer(3, GL_FIXED, 0, g_vertex_buffer_data);
		// ATTN: OTHER BINDING AND DRAWING COMMANDS GO HERE, one set per object:
		//glBindVertexArray(VertexArrayId[<x>]); etc etc
		//Setting white line
			glBindVertexArray(VertexArrayId[1]);
			glBindBuffer(GL_ARRAY_BUFFER, VertexBufferId[1]);
			glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertices2), Vertices2);
			glDrawArrays(GL_LINE_STRIP, 0, 9);
			//When press '2', show and hide Bezier Curve
			if (fm2&&glfwGetKey(window, GLFW_KEY_2)==GLFW_PRESS){
				fm2 = false;
				cooot2++;
				KeyLastFrame = glfwGetKey(window, GLFW_KEY_2);
			}
			if (KeyLastFrame == GLFW_PRESS&&glfwGetKey(window, GLFW_KEY_2) == GLFW_RELEASE) fm2 = true;
			if (cooot2 == 1){
				glBindVertexArray(VertexArrayId[6]);
				glBindBuffer(GL_ARRAY_BUFFER, VertexBufferId[6]);
				glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertices7), Vertices7);
				glDrawElements(GL_POINTS, NumVert[6], GL_UNSIGNED_SHORT, (void*)0);
				glBindVertexArray(VertexArrayId[7]);
				glBindBuffer(GL_ARRAY_BUFFER, VertexBufferId[7]);
				glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertices8), Vertices8);
				glDrawElements(GL_LINE_LOOP, NumVert[7], GL_UNSIGNED_SHORT, (void*)0);
			}
			else cooot2 = 0;
			//When press '1', show and hide subdivision Curve
			if (fm&&glfwGetKey(window, GLFW_KEY_1)==GLFW_PRESS){
				cooot++;
				fm = false;
				KeyLastFrame2 = glfwGetKey(window, GLFW_KEY_1);
			}
			if (KeyLastFrame2 == GLFW_PRESS&&glfwGetKey(window, GLFW_KEY_1) == GLFW_RELEASE) fm = true;
				if (cooot == 1){
					glBindVertexArray(VertexArrayId[2]);
					glBindBuffer(GL_ARRAY_BUFFER, VertexBufferId[2]);
					glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertices3), Vertices3);
					glDrawElements(GL_LINE_LOOP, NumVert[2], GL_UNSIGNED_SHORT, (void*)0);
				}
				else if (cooot == 2){
					glBindVertexArray(VertexArrayId[3]);
					glBindBuffer(GL_ARRAY_BUFFER, VertexBufferId[3]);
					glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertices4), Vertices4);
					glDrawElements(GL_LINE_LOOP, NumVert[3], GL_UNSIGNED_SHORT, (void*)0);
				}
				else if (cooot == 3){
					glBindVertexArray(VertexArrayId[4]);
					glBindBuffer(GL_ARRAY_BUFFER, VertexBufferId[4]);
					glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertices5), Vertices5);
					glDrawElements(GL_LINE_LOOP, NumVert[4], GL_UNSIGNED_SHORT, (void*)0);
				}
				else if (cooot == 4){
					glBindVertexArray(VertexArrayId[5]);
					glBindBuffer(GL_ARRAY_BUFFER, VertexBufferId[5]);
					glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertices6), Vertices6);
					glDrawElements(GL_LINE_LOOP, NumVert[5], GL_UNSIGNED_SHORT, (void*)0);
				}
				else if (cooot == 5){ cooot = 0; }
			//if (glfwGetKey(window, GLFW_KEY_1) == GLFW_RELEASE) KeyLastFrame = true;
		glBindVertexArray(0);
	}
	glUseProgram(0);
	// Draw GUI
	TwDraw();

	// Swap buffers
	glfwSwapBuffers(window);
	glfwPollEvents();
}

void pickVertex(void)
{
	// Clear the screen in white
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glUseProgram(pickingProgramID);
	{
		glm::mat4 ModelMatrix = glm::mat4(1.0); // TranslationMatrix * RotationMatrix;
		glm::mat4 MVP = gProjectionMatrix * gViewMatrix * ModelMatrix;

		// Send our transformation to the currently bound shader, in the "MVP" uniform
		glUniformMatrix4fv(PickingMatrixID, 1, GL_FALSE, &MVP[0][0]);
		glUniform1fv(pickingColorArrayID, NumVert[0], pickingColor);	// here we pass in the picking marker array

		// Draw the ponts
		glEnable(GL_PROGRAM_POINT_SIZE);
		glBindVertexArray(VertexArrayId[0]);
		glBindBuffer(GL_ARRAY_BUFFER, VertexBufferId[0]);
		glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertices), Vertices);	// update buffer data
		glDrawElements(GL_POINTS, NumVert[0], GL_UNSIGNED_SHORT, (void*)0);
		glBindVertexArray(0);
	}
	glUseProgram(0);
	// Wait until all the pending drawing commands are really done.
	// Ultra-mega-over slow !
	// There are usually a long time between glDrawElements() and
	// all the fragments completely rasterized.
	glFlush();
	glFinish();

	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

	// Read the pixel at the center of the screen.
	// You can also use glfwGetMousePos().
	// Ultra-mega-over slow too, even for 1 pixel,
	// because the framebuffer is on the GPU.
	double xpos, ypos;
	glfwGetCursorPos(window, &xpos, &ypos);
	unsigned char data[4];
	glReadPixels(xpos, window_height - ypos, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data); // OpenGL renders with (0,0) on bottom, mouse reports with (0,0) on top

	// Convert the color back to an integer ID
	gPickedIndex = int(data[0]);

	// Uncomment these lines to see the picking shader in effect
	//glfwSwapBuffers(window);
	//continue; // skips the normal rendering
}

// fill this function in!
void moveVertex(void)
{
	glm::mat4 ModelMatrix = glm::mat4(1.0);
	GLint viewport[4];
	double xpos, ypos;
	glGetIntegerv(GL_VIEWPORT, viewport);
	glm::vec4 vp = glm::vec4(viewport[0], viewport[1], viewport[2], viewport[3]);
	//move points
	glfwGetCursorPos(window, &xpos, &ypos);
	vec3 sd=glm::unProject(glm::vec3(xpos,ypos,0.0),ModelMatrix,gProjectionMatrix,vp);
	float sda[4] = { -sd[0], -sd[1], 0.0f, 1.0f };
	// retrieve your cursor position
	// get your world coordinates
	// move points

	if (gPickedIndex >7){ // Full white, must be the background !
		gMessage = "background";
	}
	else if (gPickedIndex == 0){
		std::ostringstream oss;
		oss << "point " << gPickedIndex;
		gMessage = oss.str();
		Vertices[gPickedIndex].SetCoords(sda);
		Vertices2[gPickedIndex].SetCoords(sda);
		Vertices2[8].SetCoords(sda);
	}
	else {
		std::ostringstream oss;
		oss << "point " << gPickedIndex;
		gMessage = oss.str();
		Vertices[gPickedIndex].SetCoords(sda);
		Vertices2[gPickedIndex].SetCoords(sda);
	}
}

int initWindow(void)
{
	// Initialise GLFW
	if (!glfwInit()) {
		fprintf(stderr, "Failed to initialize GLFW\n");
		return -1;
	}

	glfwWindowHint(GLFW_SAMPLES, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

	// Open a window and create its OpenGL context
	window = glfwCreateWindow(window_width, window_height, "Liu,Bohan(66127941)", NULL, NULL);
	if (window == NULL) {
		fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n");
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);

	// Initialize GLEW
	glewExperimental = true; // Needed for core profile
	if (glewInit() != GLEW_OK) {
		fprintf(stderr, "Failed to initialize GLEW\n");
		return -1;
	}

	// Initialize the GUI
	TwInit(TW_OPENGL_CORE, NULL);
	TwWindowSize(window_width, window_height);
	TwBar * GUI = TwNewBar("Picking");
	TwSetParam(GUI, NULL, "refresh", TW_PARAM_CSTRING, 1, "0.1");
	TwAddVarRW(GUI, "Last picked object", TW_TYPE_STDSTRING, &gMessage, NULL);

	// Set up inputs
	glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_FALSE);
	glfwSetCursorPos(window, window_width / 2, window_height / 2);
	glfwSetMouseButtonCallback(window, mouseCallback);

	return 0;
}

void initOpenGL(void)
{
	// Dark blue background
	glClearColor(0.0f, 0.0f, 0.4f, 0.0f);

	// Enable depth test
	glEnable(GL_DEPTH_TEST);
	// Accept fragment if it closer to the camera than the former one
	glDepthFunc(GL_LESS);
	// Cull triangles which normal is not towards the camera
	glEnable(GL_CULL_FACE);

	// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
	//glm::mat4 ProjectionMatrix = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
	// Or, for an ortho camera :
	gProjectionMatrix = glm::ortho(-4.0f, 4.0f, -3.0f, 3.0f, 0.0f, 100.0f); // In world coordinates

	// Camera matrix
	gViewMatrix = glm::lookAt(
		glm::vec3(0, 0, -5), // Camera is at (4,3,3), in World Space
		glm::vec3(0, 0, 0), // and looks at the origin
		glm::vec3(0, 1, 0)  // Head is up (set to 0,-1,0 to look upside-down)
		);

	// Create and compile our GLSL program from the shaders
	programID = LoadShaders("StandardShading.vertexshader", "StandardShading.fragmentshader");
	pickingProgramID = LoadShaders("Picking.vertexshader", "Picking.fragmentshader");

	// Get a handle for our "MVP" uniform
	MatrixID = glGetUniformLocation(programID, "MVP");
	ViewMatrixID = glGetUniformLocation(programID, "V");
	ModelMatrixID = glGetUniformLocation(programID, "M");
	PickingMatrixID = glGetUniformLocation(pickingProgramID, "MVP");
	// Get a handle for our "pickingColorID" uniform
	pickingColorArrayID = glGetUniformLocation(pickingProgramID, "PickingColorArray");
	pickingColorID = glGetUniformLocation(pickingProgramID, "PickingColor");
	// Get a handle for our "LightPosition" uniform
	LightID = glGetUniformLocation(programID, "LightPosition_worldspace");
	//Create VAOS for many scenes
	createVAOs(Vertices, Indices, sizeof(Vertices), sizeof(Indices), 0);
	createVAOs(Vertices2, Indices, sizeof(Vertices2), sizeof(Indices), 1);
	createObjects();
    createVAOs(Vertices3, Indices2, sizeof(Vertices3), sizeof(Indices2), 2);
    createVAOs(Vertices4, Indices3, sizeof(Vertices4), sizeof(Indices3), 3);
    createVAOs(Vertices5, Indices4, sizeof(Vertices5), sizeof(Indices4), 4);
    createVAOs(Vertices6, Indices5, sizeof(Vertices6), sizeof(Indices5), 5);
	createVAOs(Vertices7, Indices6, sizeof(Vertices7), sizeof(Indices6), 6);
	createVAOs(Vertices8, Indices7, sizeof(Vertices8), sizeof(Indices7), 7);

	// ATTN: create VAOs for each of the newly created objects here:
	// createVAOs(<fill this appropriately>);

}

void createVAOs(Vertex Vertices[], unsigned short Indices[], size_t BufferSize, size_t IdxBufferSize, int ObjectId) {

	NumVert[ObjectId] = IdxBufferSize / (sizeof GLubyte);

	GLenum ErrorCheckValue = glGetError();
	size_t VertexSize = sizeof(Vertices[0]);
	size_t RgbOffset = sizeof(Vertices[0].XYZW);

	// Create Vertex Array Object
	glGenVertexArrays(1, &VertexArrayId[ObjectId]);
	glBindVertexArray(VertexArrayId[ObjectId]);

	// Create Buffer for vertex data
	glGenBuffers(1, &VertexBufferId[ObjectId]);
	glBindBuffer(GL_ARRAY_BUFFER, VertexBufferId[ObjectId]);
	glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW);

	// Create Buffer for indices
	glGenBuffers(1, &IndexBufferId[ObjectId]);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId[ObjectId]);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, IdxBufferSize, Indices, GL_STATIC_DRAW);

	// Assign vertex attributes
	glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, VertexSize, 0);
	glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid*)RgbOffset);

	glEnableVertexAttribArray(0);	// position
	glEnableVertexAttribArray(1);	// color

	// Disable our Vertex Buffer Object
	glBindVertexArray(0);

	ErrorCheckValue = glGetError();
	if (ErrorCheckValue != GL_NO_ERROR)
	{
		fprintf(
			stderr,
			"ERROR: Could not create a VBO: %s \n",
			gluErrorString(ErrorCheckValue)
			);
	}
}

void cleanup(void)
{
	// Cleanup VBO and shader
	for (int i = 0; i < NumObjects; i++) {
		glDeleteBuffers(1, &VertexBufferId[i]);
		glDeleteBuffers(1, &IndexBufferId[i]);
		glDeleteVertexArrays(1, &VertexArrayId[i]);
	}
	glDeleteProgram(programID);
	glDeleteProgram(pickingProgramID);

	// Close OpenGL window and terminate GLFW
	glfwTerminate();
}

static void mouseCallback(GLFWwindow* window, int button, int action, int mods)
{
	if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
		pickVertex();
	}
}

int main(void)
{
	// initialize window
	int errorCode = initWindow();
	if (errorCode != 0)
		return errorCode;

	// initialize OpenGL pipeline
	initOpenGL();

	// For speed computation
	double lastTime = glfwGetTime();
	int nbFrames = 0;
	do {
		// Measure speed
		double currentTime = glfwGetTime();
		nbFrames++;
		if (currentTime - lastTime >= 1.0){ // If last prinf() was more than 1sec ago
			// printf and reset
			printf("%f ms/frame\n", 1000.0 / double(nbFrames));
			nbFrames = 0;
			lastTime += 1.0;
		}

		// DRAGGING: move current (picked) vertex with cursor
		if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT))
		{
			moveVertex();
			//RightMouseBUttonPressedLastFrame = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT);
		}

		// DRAWING SCENE
		createObjects();	// re-evaluate curves in case vertices have been moved
		drawScene();


	} // Check if the ESC key was pressed or the window was closed
	while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
	glfwWindowShouldClose(window) == 0);

	cleanup();

	return 0;
}

效果如圖


發佈了38 篇原創文章 · 獲贊 5 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章