和绘制圆一样的思路,八分法绘制椭圆,借助上面的参数方程,以原点为(0,0)为例,上代码:
椭圆的绘制
构建椭圆类代码解释运行结果情况一:长轴在x轴情况二:长轴在y轴情况三:长轴等于短轴(圆)构建椭圆类
#pragma once#include <vector>#include <glm\glm.hpp>using namespace std;class Ellipse{private://顶点vector<glm::vec3> vertices;//法线vector<glm::vec3> normals;//纹理坐标vector<glm::vec2> texCoords;//索引vector<int> indices;//顶点个数int numVertices;//索引个数int numIndices;//长轴,x轴float longAxis;//短轴,y轴float shortAxis;void init(int prec);public:Ellipse();Ellipse(float longAxis, float shortAxis, int prec);float toRadians(float degrees);vector<glm::vec3> getVertices();vector<glm::vec3> getNormals();vector<glm::vec2> getTexCoords();vector<int> getIndices();int getNumVertices();int getNumIndices();};
#include "Ellipse.h"Ellipse::Ellipse(){}Ellipse::Ellipse(float longAxis, float shortAxis, int prec){this->longAxis = longAxis;this->shortAxis = shortAxis;init(prec);}float Ellipse::toRadians(float degrees) {float pi = acos(-1.0);return (degrees * 2.0f * pi) / 360.0f;}void Ellipse::init(int prec){numVertices = prec + 1;numIndices = prec * 3;for (int i = 0; i < numVertices; i++){vertices.push_back(glm::vec3());normals.push_back(glm::vec3());texCoords.push_back(glm::vec2(0.5f, 0.25f));}for (int i = 0; i < numIndices; i++){indices.push_back(0);}for (int i = 0; i < prec; i++){float degrees, radians;if (i < prec / 2){degrees = i * 360.f / (prec / 2);radians = toRadians(degrees);}else {degrees = -((i - prec / 2) * 360.f) / (prec / 2);radians = toRadians(degrees);}float x = longAxis * cos(radians);float y = shortAxis * sin(radians);float s, t;vertices[i] = glm::vec3(x, y, 0.f);normals[i] = glm::vec3(1.0f, 1.f, 1.f);float product;if (longAxis > shortAxis){product = shortAxis / (2 * longAxis);if (x >= 0){s = 0.5 + x / (2 * longAxis);}else{s = 0.5 - (fabsf(x) / (2 * longAxis));}if (y >= 0){t = product + y / (2 * longAxis);}else {t = product - fabsf(y / (2 * longAxis));}}else{product = longAxis / (2 * shortAxis);if (x >= 0){s = product + x / (2 * shortAxis);}else{s = product - (fabsf(x) / (2 * shortAxis));}if (y >= 0){t = 0.5 + y / (2 * shortAxis);}else {t = 0.5 - fabsf(y / (2 * shortAxis));}}texCoords[i] = glm::vec2(s, t);}for (int i = 0; i < prec; i++){if (i == prec - 1){indices[3 * i + 0] = i;indices[3 * i + 1] = 0;indices[3 * i + 2] = prec;break;}indices[3 * i + 0] = i;indices[3 * i + 1] = i + 1;indices[3 * i + 2] = prec;}}vector<glm::vec3> Ellipse::getVertices(){return vertices;}vector<glm::vec3> Ellipse::getNormals(){return normals;}vector<glm::vec2> Ellipse::getTexCoords(){return texCoords;}vector<int> Ellipse::getIndices(){return indices;}int Ellipse::getNumVertices(){return numVertices;}int Ellipse::getNumIndices(){return numIndices;}
代码解释
if (longAxis > shortAxis){product = shortAxis / (2 * longAxis);if (x >= 0){s = 0.5 + x / (2 * longAxis);}else{s = 0.5 - (fabsf(x) / (2 * longAxis));}if (y >= 0){t = product + y / (2 * longAxis);}else {t = product - fabsf(y / (2 * longAxis));}}else{product = longAxis / (2 * shortAxis);if (x >= 0){s = product + x / (2 * shortAxis);}else{s = product - (fabsf(x) / (2 * shortAxis));}if (y >= 0){t = 0.5 + y / (2 * shortAxis);}else {t = 0.5 - fabsf(y / (2 * shortAxis));}}texCoords[i] = glm::vec2(s, t);}
此段代码中的判断代表了两种情况的椭圆,一种是x轴向为长轴,y轴向为短轴,另一种则是x轴向为短轴,y轴向为长轴的uv坐标的计算。