ported the University CGI demo from WINDOWS + GLUT + GLEW + GLU + OpenGL 4 to LINUX WAYLAND + EGL + GLES 2 with minimal cuts
This commit is contained in:
128
GL_STUFF/SOURCES/CURVES/NURBS.cpp
Executable file
128
GL_STUFF/SOURCES/CURVES/NURBS.cpp
Executable file
@@ -0,0 +1,128 @@
|
||||
#include "../../HEADERS/CURVES/NURBS.hpp"
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
void NURBS::preliminaryChecks() {
|
||||
int nPoints = controlPoints->size();
|
||||
int nWeights = weights->size();
|
||||
int nBoundaries = intervalBoundaries->size();
|
||||
int nMultiplicities = multiplicities->size();
|
||||
int requiredBoundaries = order + 1;
|
||||
for (int i = 0; i < nMultiplicities; i++)
|
||||
requiredBoundaries += multiplicities->operator[](i);
|
||||
|
||||
std::cout << "nPoints : " << nPoints << std::endl;
|
||||
std::cout << "nWeights : " << nWeights << std::endl;
|
||||
std::cout << "nBoundaries : " << nBoundaries << std::endl;
|
||||
std::cout << "nMultiplicities : " << nMultiplicities << std::endl;
|
||||
std::cout << "requiredBoundaries : " << requiredBoundaries << std::endl;
|
||||
|
||||
if (nWeights != nPoints)
|
||||
throw std::invalid_argument("NURBS : nPoints <> nWeights");
|
||||
if (nMultiplicities != (nPoints)) {
|
||||
std::stringstream err;
|
||||
err << "NURBS : nPoints (" << nPoints << ") <> nMultiplicities (" << nMultiplicities << ")";
|
||||
throw std::invalid_argument(err.str());
|
||||
}
|
||||
|
||||
if (nBoundaries != requiredBoundaries) {
|
||||
std::stringstream err;
|
||||
err << "NURBS : nBoundaries (" << nBoundaries << ") <> should be equal to Order + sum (multiplicities) (" << requiredBoundaries << ")";
|
||||
throw std::invalid_argument(err.str());
|
||||
}
|
||||
}
|
||||
|
||||
NURBS::NURBS( unsigned int order, vector<glm::vec3>* points, vector<float>* weights, vector<float>* boundaries, vector<unsigned int>* multiplicities) : Curve{ points , boundaries} {
|
||||
this->order = order;
|
||||
this->weights = weights;
|
||||
this->intervalBoundaries = boundaries;
|
||||
this->multiplicities = multiplicities;
|
||||
preliminaryChecks();
|
||||
derivativePoints = new vector<glm::vec3>();
|
||||
derivativeWeghts = new vector<float>();
|
||||
derivativeBoundaries = new vector<float>();
|
||||
|
||||
for (int i = 0; i < controlPoints->size() - 1; i++) {
|
||||
|
||||
glm::vec3 point = ((float)order) * ((*controlPoints)[i + 1] - (*controlPoints)[i])
|
||||
/ ((*intervalBoundaries)[i + order + 1] - (*intervalBoundaries)[i + 1]);
|
||||
derivativePoints->push_back(point);
|
||||
//not so sure about this
|
||||
derivativeWeghts->push_back(weights->at(i));
|
||||
|
||||
}
|
||||
|
||||
for (int i = 1; i < intervalBoundaries->size() - 1; i++)
|
||||
derivativeBoundaries->push_back(intervalBoundaries->operator[](i));
|
||||
}
|
||||
|
||||
glm::vec3 NURBS::deBoor(float at, int index) {
|
||||
if (order < 0) {
|
||||
throw std::invalid_argument("NURBS : evaluateBasis order underflow");
|
||||
}
|
||||
else {
|
||||
vector<glm::vec3> points = vector<glm::vec3>();
|
||||
vector<float> wei = vector<float>(); //
|
||||
int firstPointIndex = index - order;
|
||||
for (int i = index - order; i <= index; i++) {
|
||||
float w = weights->operator[](i);
|
||||
points.push_back(controlPoints->operator[](i) * w);
|
||||
wei.push_back(w); //
|
||||
}
|
||||
for (int j = 0; j < order; j++) {
|
||||
for (int i = index - order + j + 1; i <= index; i++) {
|
||||
int pointIndex = i - index + order;
|
||||
float denominator = ((*intervalBoundaries)[i + order - j] - (*intervalBoundaries)[i]);
|
||||
if (denominator != 0.0f){
|
||||
points[pointIndex] = (points[pointIndex] * (at - (*intervalBoundaries)[i]) + ((*intervalBoundaries)[i + order - j] - at) * points[pointIndex - 1])
|
||||
/ denominator;
|
||||
wei[pointIndex] = (wei[pointIndex] * (at - (*intervalBoundaries)[i]) + ((*intervalBoundaries)[i + order - j] - at) * wei[pointIndex - 1])
|
||||
/ denominator;
|
||||
}
|
||||
}
|
||||
}
|
||||
return points[order] / wei[order];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
glm::vec3 NURBS::evaluate(float at) {
|
||||
//std::cout << "eval at " << at << std::endl;
|
||||
for(int i = order; i < intervalBoundaries->size() - order - 1; i++)
|
||||
if ((intervalBoundaries->operator[](i) <= at) && (at < intervalBoundaries->operator[](i + 1))) {
|
||||
return deBoor(at, i);
|
||||
}
|
||||
if (pow(at - getRightBound(), 2) < 1e-8)
|
||||
return deBoor(at, intervalBoundaries->size() - order - 2);
|
||||
|
||||
throw std::invalid_argument("NURBS : evaluation out of range");
|
||||
|
||||
}
|
||||
|
||||
glm::vec3 NURBS::derivate(float at) {
|
||||
vector<glm::vec3>* swapPoints = controlPoints;
|
||||
vector<float>* swapWeights = weights;
|
||||
vector<float>* swapBoundaries = intervalBoundaries;
|
||||
|
||||
controlPoints = derivativePoints;
|
||||
weights = derivativeWeghts;
|
||||
intervalBoundaries = derivativeBoundaries;
|
||||
|
||||
order--;
|
||||
glm::vec3 result = evaluate(at);
|
||||
order++;
|
||||
|
||||
controlPoints = swapPoints;
|
||||
weights = swapWeights;
|
||||
intervalBoundaries = swapBoundaries;
|
||||
return result;
|
||||
}
|
||||
|
||||
float NURBS::getLeftBound() {
|
||||
return intervalBoundaries->at(order);
|
||||
}
|
||||
|
||||
float NURBS::getRightBound() {
|
||||
return intervalBoundaries->at(intervalBoundaries->size() - order - 1);
|
||||
}
|
||||
Reference in New Issue
Block a user