Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <glew.h>
- #include <glfw3.h>
- #include <math.h>
- #include <iostream>
- #include <fstream>
- #include <string>
- #include "glm/ext.hpp"
- const float PI = 22.0f / 7.0f;
- const float DEG_TO_RAD = PI / 180.0f;
- class Vertex
- {
- public:
- GLfloat x, y, z;
- Vertex(float _x = 0, float _y = 0, float _z = 0)
- {
- x = _x;
- y = _y;
- z = _z;
- }
- Vertex operator - (const Vertex& another)
- {
- Vertex temp(x, y, z);
- temp.x -= another.x;
- temp.y -= another.y;
- temp.z -= another.z;
- return temp;
- }
- Vertex operator + (const Vertex& another)
- {
- Vertex temp(x, y, z);
- temp.x += another.x;
- temp.y += another.y;
- temp.z += another.z;
- return temp;
- }
- void operator = (const Vertex& another)
- {
- x = another.x;
- y = another.y;
- z = another.z;
- }
- Vertex operator * (float multiplier)
- {
- Vertex temp(x, y, z);
- temp.x *= multiplier;
- temp.y *= multiplier;
- temp.z *= multiplier;
- return temp;
- }
- Vertex operator * (const Vertex& another)
- {
- Vertex temp(x, y, z);
- temp.x *= another.x;
- temp.y *= another.y;
- temp.z *= another.z;
- return temp;
- }
- void Print()
- {
- printf("%f %f %f\n", x, y, z);
- }
- void Normalize()
- {
- float length = pow(pow(x, 2.0f) + pow(y, 2.0f) + pow(z, 2.0f), 0.5f);
- x /= length;
- y /= length;
- z /= length;
- }
- };
- float GetLength(const Vertex& vector)
- {
- float length = pow(vector.x, 2) + pow(vector.y, 2) + pow(vector.z, 2);
- length = pow(length, 0.5);
- return length;
- }
- Vertex GetNormal(Vertex& a, Vertex& b, Vertex& c, bool clockwise = true)
- {
- Vertex v0 = b - a;
- Vertex v1 = c - a;
- Vertex normal;
- normal.x = (v0.y * v1.z) - (v0.z * v1.y);
- normal.y = -1.0f * ((v0.x * v1.z) - (v0.z * v1.x));
- normal.z = (v0.x * v1.y) - (v0.y - v1.x);
- float length = GetLength(normal);
- normal.x = normal.x * (clockwise ? 1.0f : -1.0f) / length;
- normal.y = normal.y * (clockwise ? 1.0f : -1.0f) / length;
- normal.z = normal.z * (clockwise ? 1.0f : -1.0f) / length;
- return normal;
- }
- float GetDotProduct(const Vertex& a, const Vertex& b)
- {
- float dot = a.x * b.x + a.y * b.y + a.z * b.z;
- return dot;
- }
- float GetDistance(const Vertex& a, const Vertex& b)
- {
- float distance = pow((a.x - b.x), 2.0) + pow((a.y - b.y), 2.0) + pow((a.z - b.z), 2.0);
- distance = pow(distance, 0.5);
- return distance;
- }
- Vertex GetRotationResult(const Vertex& pivot, const Vertex* matrix, Vertex point, bool isEuler = false)
- {
- Vertex temp, newPosition;
- temp = (isEuler) ? point : point - pivot;
- newPosition.x = temp.x * matrix[0].x + temp.y * matrix[0].y + temp.z * matrix[0].z;
- newPosition.y = temp.x * matrix[1].x + temp.y * matrix[1].y + temp.z * matrix[1].z;
- newPosition.z = temp.x * matrix[2].x + temp.y * matrix[2].y + temp.z * matrix[2].z;
- temp = (isEuler) ? newPosition : newPosition + pivot;
- return temp;
- }
- void GetRotationMatrix(const Vertex& vector, float angle, Vertex* matrix)
- {
- matrix[0].x = (cos(angle) + pow(vector.x, 2.0f) * (1.0f - cos(angle)));
- matrix[0].y = (vector.x * vector.y * (1.0f - cos(angle)) - vector.z * sin(angle));
- matrix[0].z = (vector.x * vector.z * (1.0f - cos(angle)) + vector.y * sin(angle));
- matrix[1].x = (vector.x * vector.y * (1.0f - cos(angle)) + vector.z * sin(angle));
- matrix[1].y = (cos(angle) + pow(vector.y, 2.0f) * (1.0f - cos(angle)));
- matrix[1].z = (vector.y * vector.z * (1.0f - cos(angle)) - vector.x * sin(angle));
- matrix[2].x = (vector.x * vector.z * (1.0f - cos(angle)) - vector.y * sin(angle));
- matrix[2].y = (vector.y * vector.z * (1.0f - cos(angle)) + vector.x * sin(angle));
- matrix[2].z = (cos(angle) + pow(vector.z, 2.0f) * (1.0f - cos(angle)));
- }
- int GetPascal(int row, int col)
- {
- if (col > row)
- {
- return 0;
- }
- else if (col == 0 || row == 0)
- {
- return 1;
- }
- return GetPascal(row - 1, col - 1) + GetPascal(row - 1, col);
- }
- class Shape
- {
- protected:
- int point_size;
- int outline_point_size;
- int color_size;
- int normal_count;
- Vertex* points;
- Vertex* outline_points;
- Vertex* base_colors;
- Vertex* colors;
- Vertex* normals;
- Vertex position;
- Vertex euler[3]; //euler X, euler Y, euler Z
- GLuint buffer;
- GLuint outlineBuffer;
- GLuint shader, outlineShader;
- GLuint MatrixID;
- GLuint colorBuffer;
- glm::mat4 mvp;
- public:
- Shape(float _x = 0, float _y = 0, float _z = 0)
- {
- position = Vertex(_x, _y, _z);
- euler[0] = Vertex(1, 0, 0);
- euler[1] = Vertex(0, 1, 0);
- euler[2] = Vertex(0, 0, 1);
- normal_count = 0;
- }
- Vertex GetPosition()
- {
- return position;
- }
- int GetPointSize()
- {
- return point_size;
- }
- int GetOutlinePointSize()
- {
- return outline_point_size;
- }
- Vertex* GetPoints()
- {
- return points;
- }
- Vertex* GetOutlinePoints()
- {
- return outline_points;
- }
- void ShowPoints()
- {
- for (int i = 0; i < point_size; i++)
- {
- printf("%f, %f, %f\n", points[i].x, points[i].y, points[i].z);
- }
- }
- void InitializeBuffer()
- {
- glGenBuffers(1, &buffer);
- glGenBuffers(1, &outlineBuffer);
- glGenBuffers(1, &colorBuffer);
- SetArrayBuffer();
- }
- void SetArrayBuffer()
- {
- SetBuffer();
- SetOutlineBuffer();
- SetColorBuffer();
- }
- void SetBuffer()
- {
- glBindBuffer(GL_ARRAY_BUFFER, buffer);
- glBufferData(GL_ARRAY_BUFFER, GetPointSize() * sizeof(GL_FLOAT) * 3, GetPoints(), GL_STATIC_DRAW);
- }
- void SetOutlineBuffer()
- {
- glBindBuffer(GL_ARRAY_BUFFER, outlineBuffer);
- glBufferData(GL_ARRAY_BUFFER, GetOutlinePointSize() * sizeof(GL_FLOAT) * 3, GetOutlinePoints(), GL_STATIC_DRAW);
- }
- void SetColorBuffer()
- {
- glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
- glBufferData(GL_ARRAY_BUFFER, color_size * sizeof(GL_FLOAT) * 3, colors, GL_STATIC_DRAW);
- }
- void InitializeShader(const char vertex[], const char fragment[])
- {
- shader = LoadShaders(vertex, fragment);
- glm::mat4 Projection = glm::perspective(90.0f * DEG_TO_RAD, 1.0f, 0.1f, 100.0f);
- // Camera matrix
- glm::mat4 View = glm::lookAt(
- glm::vec3(0, 1, 2), //Eye position at (0, 1, 2)
- 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)
- );
- // Model matrix : an identity matrix (model will be at the origin)
- glm::mat4 Model = glm::mat4(1.0f);
- // Our ModelViewProjection : multiplication of our 3 matrices
- mvp = Projection * View * Model;
- MatrixID = glGetUniformLocation(shader, "MVP");
- }
- void InitializeOutlineShader(const char vertex[], const char fragment[])
- {
- outlineShader = LoadShaders(vertex, fragment);
- }
- void BindBuffer()
- {
- glEnableVertexAttribArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, buffer);
- glVertexAttribPointer(
- 0, //Set to 0 for coordinates
- 3,
- GL_FLOAT,
- GL_FALSE,
- 0,
- 0
- );
- glEnableVertexAttribArray(1);
- glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
- glVertexAttribPointer(
- 1, //Set to 1 for colors
- 3,
- GL_FLOAT,
- GL_FALSE,
- 0,
- 0
- );
- }
- void BindOutlineBuffer()
- {
- glEnableVertexAttribArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, outlineBuffer);
- glVertexAttribPointer(
- 0,
- 3,
- GL_FLOAT,
- GL_FALSE,
- 0,
- 0
- );
- }
- void DrawPolygon()
- {
- glUseProgram(shader);
- glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &mvp[0][0]);
- BindBuffer();
- glDrawArrays(GL_TRIANGLES, 0, GetPointSize());
- }
- void DrawPolyline()
- {
- glUseProgram(outlineShader);
- glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &mvp[0][0]);
- BindOutlineBuffer();
- glDrawArrays(GL_LINES, 0, GetOutlinePointSize());
- }
- void Rotate(const Vertex& pivot, const Vertex& vector, float angle)
- {
- angle = angle * DEG_TO_RAD;
- Vertex* rotation_matrix = new Vertex[3];
- GetRotationMatrix(vector, angle, rotation_matrix);
- //Rotate all the points
- for (int i = 0; i < point_size; i++)
- {
- points[i] = GetRotationResult(pivot, rotation_matrix, points[i]);
- }
- for (int i = 0; i < outline_point_size; i++)
- {
- outline_points[i] = GetRotationResult(pivot, rotation_matrix, outline_points[i]);
- }
- //Rotate the euler direction
- for (int i = 0; i < 3; i++)
- {
- euler[i] = GetRotationResult(pivot, rotation_matrix, euler[i], true);
- euler[i].Normalize(); //Normalize the euler since we only need the euler's direction
- }
- //Rotate the normals
- for (int i = 0; i < normal_count; i++)
- {
- normals[i] = GetRotationResult(pivot, rotation_matrix, normals[i], true);
- }
- position = GetRotationResult(pivot, rotation_matrix, position);
- SetArrayBuffer();
- }
- void Translate(const Vertex& movement)
- {
- for (int i = 0; i < point_size; i++)
- {
- points[i] = points[i] + movement;
- }
- for (int i = 0; i < outline_point_size; i++)
- {
- outline_points[i] = outline_points[i] + movement;
- }
- position = position + movement;
- SetArrayBuffer();
- }
- Vertex GetEuler(int index)
- {
- return euler[index];
- }
- void ResetEuler()
- {
- euler[0] = Vertex(1, 0, 0);
- euler[1] = Vertex(0, 1, 0);
- euler[2] = Vertex(0, 0, 1);
- }
- ~Shape()
- {
- delete points;
- glDeleteBuffers(1, &buffer);
- }
- };
- class Mesh : public Shape
- {
- int vlib_count;
- int vnorm_count;
- Vertex* vlib;
- Vertex* vnorms;
- public:
- Mesh(const char file_name[], float _x = 0, float _y = 0, float _z = 0) : Shape(_x, _y, _z)
- {
- vlib_count = 0;
- vnorm_count = 0;
- point_size = 0;
- LoadVlib(file_name);
- GenerateOutlinePoints();
- GenerateColors();
- }
- void GenerateColors()
- {
- color_size = point_size;
- base_colors = new Vertex[color_size];
- colors = new Vertex[color_size];
- for (int i = 0; i < color_size; i++)
- {
- base_colors[i] = Vertex(0.9f, 0.2f, 0.8f);
- }
- }
- void CalculateColors(Vertex& light_source, Vertex& light_color, const Vertex& ambience_multiplier, Vertex& eye_pos, const float& specular_multiplier, const float& shinyness, const float& light_intensity)
- {
- for (int i = 0; i < point_size; i++)
- {
- int normal_index = i;
- //Ambience
- Vertex ambience = base_colors[i] * ambience_multiplier;
- //Diffuse
- Vertex light_vec = light_source - points[i];
- float light_distance = GetLength(light_vec);
- light_vec = light_vec * (1.0f / light_distance);
- float cos_angle = GetDotProduct(light_vec, normals[normal_index]);
- Vertex diffuse = base_colors[i] * ((cos_angle < 0) ? 0 : cos_angle);
- //Specular
- Vertex eye_vec = eye_pos - points[i];
- float eye_distance = GetLength(eye_vec);
- eye_vec = eye_vec * (1.0f / eye_distance);
- Vertex R = normals[normal_index] * cos_angle * 2.0 - light_vec;
- R = R * (1.0f / GetLength(R));
- float spec = GetDotProduct(eye_vec, R);
- spec = (spec < 0) ? 0 : pow(spec, shinyness);
- Vertex specular = Vertex(0, 0, 0);
- if (spec > 0)
- {
- specular = light_color * specular_multiplier * spec;
- diffuse = diffuse * (1 - spec);
- }
- //Combined
- colors[i] = (ambience + diffuse + specular) * (light_intensity / (pow(light_distance, 2.0)));
- }
- SetColorBuffer();
- }
- void RandomizeColors()
- {
- for (int i = 0; i < color_size; i++)
- {
- float red = (float)(rand() % 100) / 100.0f;
- float green = (float)(rand() % 100) / 100.0f;
- float blue = (float)(rand() % 100) / 100.0f;
- colors[i] = Vertex(red, green, blue);
- }
- SetColorBuffer();
- }
- void GenerateNormals()
- {
- normal_count = point_size / 3;
- normals = new Vertex[normal_count];
- for (int i = 0, j = 0; i < point_size; i += 3, j++)
- {
- normals[j] = GetNormal(points[i], points[i + 1], points[i + 2], true);
- normals[j].x = abs(normals[j].x);
- normals[j].y = abs(normals[j].y);
- normals[j].z = abs(normals[j].z);
- }
- }
- void GenerateOutlinePoints()
- {
- outline_point_size = point_size * 2;
- outline_points = new Vertex[outline_point_size];
- for (int i = 0, j = 0; i < point_size; i += 3, j += 6)
- {
- int first_index = i;
- int second_index = i + 1;
- int third_index = i + 2;
- outline_points[j] = points[first_index];
- outline_points[j + 1] = points[second_index];
- outline_points[j + 2] = points[second_index];
- outline_points[j + 3] = points[third_index];
- outline_points[j + 4] = points[third_index];
- outline_points[j + 5] = points[first_index];
- }
- }
- void LoadVlib(const char file_name[])
- {
- std::string value;
- std::string line;
- std::ifstream mesh_file(file_name);
- if (mesh_file.is_open())
- {
- while (std::getline(mesh_file, line))
- {
- if (line.substr(0, line.find(" ")) == "v")
- {
- Vertex* temp;
- temp = vlib;
- vlib = new Vertex[vlib_count + 1];
- for (int i = 0; i < vlib_count; i++)
- {
- vlib[i] = temp[i];
- }
- float* values = new float[3];
- int value_count = 0;
- while (line.length() > 0)
- {
- line = line.substr(line.find(" ") + 1);
- while (line[0] == ' ')
- {
- line = line.substr(line.find(" ") + 1);
- }
- if (line.find(" ") != -1)
- {
- value = line.substr(0, line.find(" "));
- line = line.substr(line.find(" "));
- }
- else
- {
- value = line;
- line = "";
- }
- values[value_count] = std::stof(value);
- value_count++;
- }
- vlib[vlib_count].x = values[0];
- vlib[vlib_count].y = values[1];
- vlib[vlib_count].z = values[2];
- vlib_count++;
- delete[] temp;
- delete[] values;
- }
- if (line.substr(0, line.find(" ")) == "vn")
- {
- Vertex* temp;
- temp = vnorms;
- vnorms = new Vertex[vnorm_count + 1];
- for (int i = 0; i < vnorm_count; i++)
- {
- vnorms[i] = temp[i];
- }
- float* values = new float[3];
- int value_count = 0;
- //std::cout << line << "\n";
- while (line.length() > 0)
- {
- line = line.substr(line.find(" ") + 1);
- while (line[0] == ' ')
- {
- line = line.substr(line.find(" ") + 1);
- }
- if (line.find(" ") != -1)
- {
- value = line.substr(0, line.find(" "));
- line = line.substr(line.find(" "));
- }
- else
- {
- value = line;
- line = "";
- }
- //std::cout << value << "\n";
- values[value_count] = std::stof(value);
- value_count++;
- }
- vnorms[vnorm_count].x = values[0];
- vnorms[vnorm_count].y = values[1];
- vnorms[vnorm_count].z = values[2];
- vnorm_count++;
- delete[] temp;
- delete[] values;
- }
- if (line.substr(0, line.find(" ")) == "f")
- {
- Vertex* temp;
- Vertex* temp_n;
- temp = points;
- temp_n = normals;
- points = new Vertex[point_size + 3];
- normals = new Vertex[point_size + 3];
- for (int i = 0; i < point_size; i++)
- {
- points[i] = temp[i];
- normals[i] = temp_n[i];
- }
- int* values = new int[3];
- int* values_n = new int[3];
- int value_count = 0;
- while (line.length() > 0)
- {
- line = line.substr(line.find(" ") + 1);
- while (line[0] == ' ')
- {
- line = line.substr(line.find(" ") + 1);
- }
- if (line.find(" ") != -1)
- {
- value = line.substr(0, line.find(" "));
- line = line.substr(line.find(" "));
- }
- else
- {
- value = line;
- line = "";
- }
- std::string value_input = value.substr(0, value.find("/"));
- values[value_count] = std::stoi(value_input);
- value = value.substr(value.find("/") + 1); //vt
- value = value.substr(value.find("/") + 1); //vn
- value_input = value.substr(0, value.find("/"));
- values_n[value_count] = std::stoi(value_input);
- value_count++;
- }
- for (int i = 0; i < 3; i++)
- {
- points[point_size + i].x = vlib[values[i] - 1].x * 0.1f;
- points[point_size + i].y = vlib[values[i] - 1].y * 0.1f;
- points[point_size + i].z = vlib[values[i] - 1].z * 0.1f;
- normals[point_size + i].x = vnorms[values_n[i] - 1].x;
- normals[point_size + i].y = vnorms[values_n[i] - 1].y;
- normals[point_size + i].z = vnorms[values_n[i] - 1].z;
- }
- point_size += 3;
- delete[] temp;
- delete[] temp_n;
- delete[] values;
- delete[] values_n;
- }
- }
- mesh_file.close();
- normal_count = point_size;
- //ShowPoints();
- }
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement