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:
80
GL_STUFF/SOURCES/CURVES/Bezier.cpp
Executable file
80
GL_STUFF/SOURCES/CURVES/Bezier.cpp
Executable file
@@ -0,0 +1,80 @@
|
||||
#include "../../HEADERS/CURVES/Bezier.hpp"
|
||||
#include "iostream"
|
||||
#define LERP(t,a,b) (1 - t) * a + t * b;
|
||||
|
||||
Bezier::Bezier(unsigned int order, vector<glm::vec3> *points, vector<float> *intervals) : Curve{ points, intervals } {
|
||||
this->order = order;
|
||||
}
|
||||
|
||||
/*might be useless (using lerp based evaluation)*/
|
||||
float Bezier::evaluateBasisFunction(float at, int number, int order, float intervalLeft, float intervalRight) {
|
||||
if (number < 0 || number > order) {
|
||||
return 0;
|
||||
}
|
||||
else if (number == 0 && order == 0) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return ((at - intervalLeft)/(intervalRight - intervalLeft)) * evaluateBasisFunction(at, number - 1, order - 1, intervalLeft, intervalRight) + ((intervalRight - at) / (intervalRight - intervalLeft)) * evaluateBasisFunction(at, number, order - 1, intervalLeft, intervalRight);
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 Bezier::evaluate(float at) {
|
||||
vector<glm::vec3>partials = vector<glm::vec3>();
|
||||
for (const glm::vec3 point : *controlPoints)
|
||||
partials.push_back(point);
|
||||
int iter = partials.size() - 1;
|
||||
while (iter > 0) {
|
||||
for (int i = 0; i < iter; i++) {
|
||||
partials[i] = LERP(at, partials[i], partials[i + 1]);
|
||||
}
|
||||
iter--;
|
||||
}
|
||||
return partials[0];
|
||||
}
|
||||
|
||||
glm::vec3 Bezier::derivate(float at) {
|
||||
return glm::vec3();
|
||||
}
|
||||
|
||||
/*
|
||||
* takes as input a sequence of points
|
||||
* to be interpreted as conjoined bezier segments of order 3
|
||||
*/
|
||||
Bezier3Segments::Bezier3Segments( vector<glm::vec3>* points, vector<float>* intervals) : Bezier { ((unsigned int) points->size() - 1 ) , points , intervals } {
|
||||
int nPoints = points->size();
|
||||
assert((nPoints % 4) == 0);
|
||||
}
|
||||
|
||||
glm::vec3 Bezier3Segments::evaluate(float at) {
|
||||
for (int interval = 0; interval < intervalBoundaries->size() - 1; interval++) {
|
||||
if ((intervalBoundaries->operator[](interval) <= at) && (intervalBoundaries->operator[](interval + 1) >= at)) {
|
||||
float normalizedAt = (at - intervalBoundaries->operator[](interval)) / (intervalBoundaries->operator[](interval + 1) - intervalBoundaries->operator[](interval));
|
||||
vector<glm::vec3> partials;
|
||||
for (int j = 0; j <= 3; j++) {
|
||||
partials.push_back(controlPoints->operator[](4 * interval + j));
|
||||
}
|
||||
int count = 3;
|
||||
while (count > 0) {
|
||||
for (int j = 0; j < count; j++) {
|
||||
partials[j] = LERP(normalizedAt, partials[j], partials[j + 1]);
|
||||
}
|
||||
count--;
|
||||
}
|
||||
return partials[0];
|
||||
}
|
||||
}
|
||||
throw "Bezier3Segment evaluation out of range";
|
||||
}
|
||||
|
||||
glm::vec3 Bezier3Segments::derivate(float at) {
|
||||
return glm::vec3();
|
||||
}
|
||||
|
||||
float Bezier3Segments::getLeftBound() {
|
||||
return intervalBoundaries->front();
|
||||
}
|
||||
|
||||
float Bezier3Segments::getRightBound() {
|
||||
return intervalBoundaries->back();
|
||||
}
|
||||
34
GL_STUFF/SOURCES/CURVES/Curve.cpp
Executable file
34
GL_STUFF/SOURCES/CURVES/Curve.cpp
Executable file
@@ -0,0 +1,34 @@
|
||||
#include "../../HEADERS/CURVES/Curve.hpp"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
||||
Curve::Curve(vector<glm::vec3> *points, vector<float> *boundaries) {
|
||||
setControlPoints(points);
|
||||
setIntervalBoundaries(boundaries);
|
||||
}
|
||||
|
||||
vector<glm::vec3>* Curve::getControlPoints() {
|
||||
return controlPoints;
|
||||
}
|
||||
|
||||
vector<float>* Curve::getIntervalBoundaries() {
|
||||
return intervalBoundaries;
|
||||
}
|
||||
|
||||
void Curve::setControlPoints(vector<glm::vec3>* points) {
|
||||
controlPoints = points;
|
||||
}
|
||||
|
||||
void Curve::setIntervalBoundaries(vector<float> *boundaries) {
|
||||
intervalBoundaries = boundaries;
|
||||
}
|
||||
|
||||
float Curve::getLeftBound() {
|
||||
return intervalBoundaries->front();
|
||||
}
|
||||
|
||||
float Curve::getRightBound() {
|
||||
return intervalBoundaries->back();
|
||||
}
|
||||
|
||||
110
GL_STUFF/SOURCES/CURVES/CurveIterator.cpp
Executable file
110
GL_STUFF/SOURCES/CURVES/CurveIterator.cpp
Executable file
@@ -0,0 +1,110 @@
|
||||
#include "../../HEADERS/CURVES/CurveIterator.hpp"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
CurveIterator::CurveIterator(Curve *curve, unsigned int steps, CurveIterationMode basicOrLength) {
|
||||
this->curve = curve;
|
||||
this->steps = steps;
|
||||
this->iterationMode = basicOrLength;
|
||||
leftBound = curve->getLeftBound();
|
||||
rightBound = curve->getRightBound();
|
||||
estimatedLength = 0;
|
||||
resetIterator();
|
||||
if (iterationMode == CurveIterationMode::LENGTH) {
|
||||
computeLength();
|
||||
}
|
||||
}
|
||||
|
||||
void CurveIterator::resetIterator() {
|
||||
basicStepCounter = 0;
|
||||
lengthStepCounter = leftBound;
|
||||
lastIncrement = (rightBound - leftBound) / steps;
|
||||
//std::cout << "lastIncrement after reset is " << lastIncrement << std::endl;
|
||||
}
|
||||
|
||||
void CurveIterator::computeLength() {
|
||||
for (int i = 0; i < steps; i++) {
|
||||
glm::vec3 startPoint = curve->evaluate(leftBound + (rightBound - leftBound) * i / steps);
|
||||
glm::vec3 endPoint = curve->evaluate(leftBound + (rightBound - leftBound) * (i + 1) / steps);
|
||||
|
||||
estimatedLength += glm::length(endPoint - startPoint);
|
||||
//std::cout << "segment length " << estimatedLength << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
float CurveIterator::getStep() {
|
||||
if (iterationMode == CurveIterationMode::LENGTH) {
|
||||
return lengthStepCounter;
|
||||
}
|
||||
else {
|
||||
return leftBound + (rightBound - leftBound) * basicStepCounter / steps;
|
||||
}
|
||||
}
|
||||
|
||||
void CurveIterator::nextStep() {
|
||||
if (iterationMode == CurveIterationMode::LENGTH) {
|
||||
float increment = lastIncrement;
|
||||
//std::cout << "lastInc is " << lastIncrement << std::endl;
|
||||
//std::cout << "lstepCount is " << lengthStepCounter << std::endl;
|
||||
if ((lengthStepCounter + increment) <= rightBound) {
|
||||
glm::vec3 point1 = curve->evaluate(lengthStepCounter);
|
||||
glm::vec3 point2 = curve->evaluate(lengthStepCounter + increment);
|
||||
increment *= ((estimatedLength / steps) / glm::length(point2 - point1));
|
||||
//std::cout << "segment length " << glm::length(curve->evaluate(lengthStepCounter + increment) - curve->evaluate(lengthStepCounter)) << std::endl;
|
||||
lengthStepCounter += increment;
|
||||
lastIncrement = increment;
|
||||
}
|
||||
else { //cycle
|
||||
resetIterator();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(basicStepCounter < steps){
|
||||
basicStepCounter++;
|
||||
}
|
||||
else {
|
||||
resetIterator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CurveIterator::setProgress(float at) {
|
||||
if (at < 0 || at > 1) {
|
||||
std::stringstream err;
|
||||
err << "CurveIterator : required progress (" << at << ") is out of range [ 0 , 1 ]";
|
||||
throw std::invalid_argument(err.str());
|
||||
}
|
||||
else {
|
||||
resetIterator();
|
||||
int nSteps = at * steps;
|
||||
for (int i = 0; i < nSteps; i++)
|
||||
nextStep();
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 CurveIterator::evaluation() {
|
||||
float at;
|
||||
if (iterationMode == CurveIterationMode::LENGTH) {
|
||||
at = lengthStepCounter;
|
||||
}
|
||||
else {
|
||||
at = leftBound + (rightBound - leftBound) * basicStepCounter / steps;
|
||||
}
|
||||
//std::cout << "iterator at is " << at << std::endl;
|
||||
return curve->evaluate(at);
|
||||
}
|
||||
|
||||
glm::vec3 CurveIterator::derivation() {
|
||||
float at;
|
||||
if (iterationMode == CurveIterationMode::LENGTH) {
|
||||
at = lengthStepCounter;
|
||||
}
|
||||
else {
|
||||
at = leftBound + (rightBound - leftBound) * basicStepCounter / steps;
|
||||
}
|
||||
return curve->derivate(at);
|
||||
}
|
||||
|
||||
Curve* CurveIterator::getCurve() {
|
||||
return curve;
|
||||
}
|
||||
203
GL_STUFF/SOURCES/CURVES/CurvesLoader.cpp
Executable file
203
GL_STUFF/SOURCES/CURVES/CurvesLoader.cpp
Executable file
@@ -0,0 +1,203 @@
|
||||
#include "../../HEADERS/CURVES/CurvesLoader.hpp"
|
||||
|
||||
|
||||
string CurvesLoader::currentCurveType;
|
||||
vector<glm::vec3>* CurvesLoader::pointsBuffer;
|
||||
|
||||
vector<NURBS*> CurvesLoader::NURBSes;
|
||||
vector<Bezier3Segments*> CurvesLoader::beziers;
|
||||
|
||||
unsigned int CurvesLoader::NURBSOrder;
|
||||
NURBSType CurvesLoader::NURBS_TYPE;
|
||||
vector<float>* CurvesLoader::NURBSWeights;
|
||||
|
||||
char CurvesLoader::lineHeader[128];
|
||||
char* CurvesLoader::res;
|
||||
FILE* CurvesLoader::file;
|
||||
|
||||
std::smatch CurvesLoader::pieces;
|
||||
|
||||
|
||||
void CurvesLoader::beginCurve(string str, std::smatch pieces, std::regex regex) {
|
||||
pointsBuffer = new vector<glm::vec3>();
|
||||
NURBSWeights = new vector<float>();
|
||||
NURBS_TYPE = NURBSType::BASIC;
|
||||
//si inizia una patch di BEZIER
|
||||
if (pieces[1].str() == "BEZIER") {
|
||||
//std::cout << "next is BEZIER" << std::endl;
|
||||
currentCurveType = "BEZIER";
|
||||
}
|
||||
//si inizia una NURBS
|
||||
else if (pieces[1].str() == "NURBS") {
|
||||
//std::cout << "next is NURBS" << std::endl;
|
||||
currentCurveType = "NURBS";
|
||||
res = fgets(lineHeader, 128, file); // read curve multiplicity
|
||||
str = lineHeader;
|
||||
std::regex regex("\\s*order (\\d)\\s*(clamped|cyclic)?\\s*(\\n)?");
|
||||
if (res == NULL || !std::regex_match(str, pieces, regex)) {
|
||||
throw "expected NURBS order";
|
||||
}
|
||||
else {
|
||||
NURBSOrder = stoi(pieces[1]);
|
||||
if (pieces.length() > 2) {
|
||||
if (pieces[2].str() == "clamped") {
|
||||
NURBS_TYPE = NURBSType::CLAMPED;
|
||||
}
|
||||
else if (pieces[2].str() == "cyclic") {
|
||||
NURBS_TYPE = NURBSType::CYCLIC;
|
||||
}
|
||||
}
|
||||
else {
|
||||
NURBS_TYPE = NURBSType::BASIC;
|
||||
}
|
||||
std::cout << res << std::endl;
|
||||
}
|
||||
//std::cout << "parsed order : " << NURBSOrder << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
NURBS* CurvesLoader::BasicNURBS() {
|
||||
unsigned int nFunctions = pointsBuffer->size();
|
||||
unsigned int totalElements = NURBSOrder + nFunctions;
|
||||
vector<float>* intervals = new vector<float>();
|
||||
for (int i = 0; i <= totalElements; i++)
|
||||
intervals->push_back((float) i / totalElements);
|
||||
vector<unsigned int>* multiplicities = new vector<unsigned int>;
|
||||
for (int i = 0; i < pointsBuffer->size(); i++)
|
||||
multiplicities->push_back(1);
|
||||
return new NURBS(NURBSOrder, pointsBuffer, NURBSWeights, intervals, multiplicities);
|
||||
}
|
||||
|
||||
NURBS* CurvesLoader::ClampedNURBS() {
|
||||
unsigned int nFunctions = pointsBuffer->size();
|
||||
vector<float>* intervals = new vector<float>();
|
||||
for (int i = 0; i <= NURBSOrder; i++)
|
||||
intervals->push_back(0);
|
||||
for (int i = 1; i <= nFunctions - NURBSOrder; i++)
|
||||
intervals->push_back((float)i / (nFunctions - NURBSOrder));
|
||||
for (int i = 0; i < NURBSOrder; i++)
|
||||
intervals->push_back(1);
|
||||
vector<unsigned int>* multiplicities = new vector<unsigned int>;
|
||||
for (int i = 0; i < pointsBuffer->size(); i++)
|
||||
multiplicities->push_back(1);
|
||||
return new NURBS(NURBSOrder, pointsBuffer, NURBSWeights, intervals, multiplicities);
|
||||
}
|
||||
|
||||
NURBS* CurvesLoader::CyclicNURBS() {
|
||||
for (int i = 0; i < NURBSOrder; i++) {
|
||||
pointsBuffer->push_back(pointsBuffer->at(i));
|
||||
NURBSWeights->push_back(NURBSWeights->at(i));
|
||||
}
|
||||
unsigned int nFunctions = pointsBuffer->size();
|
||||
unsigned int totalElements = NURBSOrder + nFunctions;
|
||||
vector<float>* intervals = new vector<float>();
|
||||
for (int i = 0; i <= totalElements; i++)
|
||||
intervals->push_back((float) i/ totalElements);
|
||||
vector<unsigned int>* multiplicities = new vector<unsigned int>;
|
||||
for (int i = 0; i < pointsBuffer->size(); i++)
|
||||
multiplicities->push_back(1);
|
||||
return new NURBS(NURBSOrder, pointsBuffer, NURBSWeights, intervals, multiplicities);
|
||||
}
|
||||
|
||||
void CurvesLoader::closeNURBS(){
|
||||
try {
|
||||
switch (NURBS_TYPE) {
|
||||
case NURBSType::BASIC :
|
||||
std::cout << "NURBS was BASIC" << std::endl;
|
||||
NURBSes.push_back(BasicNURBS());
|
||||
break;
|
||||
case NURBSType::CLAMPED :
|
||||
std::cout << "NURBS was CLAMPED" << std::endl;
|
||||
NURBSes.push_back(ClampedNURBS());
|
||||
break;
|
||||
case NURBSType::CYCLIC :
|
||||
std::cout << "NURBS was CYCLIC" << std::endl;
|
||||
NURBSes.push_back(CyclicNURBS());
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (std::invalid_argument e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void CurvesLoader::closeBezier() {
|
||||
vector<float>* intervals = new vector<float>();
|
||||
int nIntervals = pointsBuffer->size() / 4;
|
||||
intervals->push_back(0);
|
||||
for (int i = 1; i <= nIntervals; i++)
|
||||
intervals->push_back((float)i / nIntervals);
|
||||
beziers.push_back(new Bezier3Segments(pointsBuffer, intervals));
|
||||
}
|
||||
|
||||
void CurvesLoader::closePendingCurve() {
|
||||
if (currentCurveType == "BEZIER") {
|
||||
closeBezier();
|
||||
}
|
||||
else if (currentCurveType == "NURBS") {
|
||||
closeNURBS();
|
||||
}
|
||||
}
|
||||
|
||||
void CurvesLoader::parseVertexData(string str) {
|
||||
vector<float> vecComponents = vector<float>();
|
||||
std::regex regex("-?\\d+.\\d+");
|
||||
while (std::regex_search(str, pieces, regex)) {
|
||||
float entry = stof(pieces[0], NULL); //potevi evitare la regex
|
||||
vecComponents.push_back(entry);
|
||||
str = pieces.suffix().str();
|
||||
}
|
||||
|
||||
glm::vec3 vec(vecComponents[0], vecComponents[1], vecComponents[2]);
|
||||
pointsBuffer->push_back(vec);
|
||||
if (currentCurveType == "NURBS") {
|
||||
NURBSWeights->push_back(vecComponents[3]);
|
||||
}
|
||||
}
|
||||
|
||||
bool CurvesLoader::loadCurves(std::string path, vector<Curve*>& curves) {
|
||||
currentCurveType = "NONE";
|
||||
pointsBuffer = new vector<glm::vec3>();
|
||||
NURBSWeights = new vector<float>();
|
||||
file = fopen(&path[0], "r");
|
||||
if (file == NULL) {
|
||||
printf("Impossible to open the curve file ! Are you in the right path ?\n");
|
||||
getchar();
|
||||
return false;
|
||||
}
|
||||
while (1) {
|
||||
res = fgets(lineHeader, 128, file); // read the first word of the line
|
||||
// EOF = End Of File. Store pending curve and quit the loop.
|
||||
if (res == NULL) {
|
||||
closePendingCurve(); //what if there was no pending curve? (aka return false)
|
||||
break;
|
||||
}
|
||||
string str = lineHeader;
|
||||
std::regex regex("\\s*curve \\d+ : (BEZIER|NURBS)\\n");
|
||||
//inizia una curva (la prima o una nuova)
|
||||
if (std::regex_match(str, pieces, regex)) {
|
||||
closePendingCurve();
|
||||
beginCurve(str, pieces, regex);
|
||||
}
|
||||
//deve essere materiale inerente la curva in costruzione
|
||||
else {
|
||||
std::regex regex("\\s*(-?\\d+.\\d+)(( , -?\\d+.\\d+)+)\\s*(\\n)?");
|
||||
//sono dati di un vertice
|
||||
if (std::regex_match(str, pieces, regex)){
|
||||
parseVertexData(str);
|
||||
}
|
||||
else {
|
||||
std::cout << "unrecognized line : " << str << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << "trovate " << beziers.size() << " curve di bezier" << std::endl << "e " << NURBSes.size() << " NURBS" << std::endl;
|
||||
for (Bezier3Segments* el : beziers)
|
||||
curves.push_back(el);
|
||||
for (NURBS* el : NURBSes)
|
||||
curves.push_back(el);
|
||||
|
||||
/* !!! only the file existence gets checked */
|
||||
return true;
|
||||
}
|
||||
|
||||
124
GL_STUFF/SOURCES/CURVES/Hermite.cpp
Executable file
124
GL_STUFF/SOURCES/CURVES/Hermite.cpp
Executable file
@@ -0,0 +1,124 @@
|
||||
#include "../../HEADERS/CURVES/Hermite.hpp"
|
||||
|
||||
#define PHI0(t) (2.0f*t*t*t - 3.0f*t*t + 1)
|
||||
#define PHI1(t) (t*t*t - 2.0f*t*t + t)
|
||||
#define PSI0(t) (-2.0f*t*t*t + 3.0f*t*t)
|
||||
#define PSI1(t) (t*t*t - t*t)
|
||||
|
||||
Hermite::Hermite(vector<glm::vec3> *points, vector<float> *intervalBoundaries)
|
||||
: Curve{ points, intervalBoundaries } {
|
||||
}
|
||||
|
||||
void Hermite::computeDerivatives(HermiteModes mode, vector<glm::vec3> auxData) {
|
||||
derivatives.clear();
|
||||
int length = (*controlPoints).size();
|
||||
switch (mode) {
|
||||
case HermiteModes::Direct:
|
||||
assert(controlPoints->size() == auxData.size());
|
||||
derivatives.push_back(auxData[0]);
|
||||
for (int i = 0; i < auxData.size() - 1; i++) {
|
||||
derivatives.push_back(auxData[i]);
|
||||
derivatives.push_back(auxData[i]);
|
||||
}
|
||||
derivatives.push_back(auxData[auxData.size() - 1]);
|
||||
break;
|
||||
case HermiteModes::Basic:
|
||||
{
|
||||
glm::vec3 result;
|
||||
result = 0.5f * ((*controlPoints)[1] - (*controlPoints)[0]) / ((*intervalBoundaries)[1] - (*intervalBoundaries)[0]);
|
||||
derivatives.push_back(result);
|
||||
for (int i = 1; i < length - 1; i++) {
|
||||
result = 0.5f *
|
||||
(
|
||||
(((*controlPoints)[i + 1] - (*controlPoints)[i])
|
||||
/ ((*intervalBoundaries)[i + 1] - (*intervalBoundaries)[i]))
|
||||
+ (((*controlPoints)[i] - (*controlPoints)[i - 1])
|
||||
/ ((*intervalBoundaries)[i] - (*intervalBoundaries)[i - 1]))
|
||||
);
|
||||
derivatives.push_back(result);
|
||||
derivatives.push_back(result);
|
||||
}
|
||||
result = 0.5f * ((*controlPoints)[length - 1] - (*controlPoints)[length - 2]) / ((*intervalBoundaries)[length - 1] - (*intervalBoundaries)[length - 2]);
|
||||
derivatives.push_back(result);
|
||||
}
|
||||
break;
|
||||
case HermiteModes::Cardinal:
|
||||
{
|
||||
assert(controlPoints->size() == auxData.size());
|
||||
int last = controlPoints->size() - 1;
|
||||
glm::vec3 delta1;
|
||||
glm::vec3 delta2;
|
||||
delta1 = (*controlPoints)[1] - (*controlPoints)[0];
|
||||
float interval1;
|
||||
float interval2;
|
||||
interval1 = (*intervalBoundaries)[1] - (*intervalBoundaries)[0];
|
||||
glm::vec3 result;
|
||||
result = 0.5f * (1 - auxData[0].x) * delta1 / interval1;
|
||||
derivatives.push_back(result);
|
||||
for (int i = 1; i < last; i++) {
|
||||
delta1 = (*controlPoints)[i + 1] - (*controlPoints)[i];
|
||||
delta2 = (*controlPoints)[i] - (*controlPoints)[i - 1];
|
||||
interval1 = (*intervalBoundaries)[i + 1] - (*intervalBoundaries)[i];
|
||||
interval2 = (*intervalBoundaries)[i] - (*intervalBoundaries)[i - 1];
|
||||
result = 0.5f * (1 - auxData[i].x) * (delta1 / interval1 + delta2 / interval2);
|
||||
derivatives.push_back(result);
|
||||
derivatives.push_back(result);
|
||||
}
|
||||
delta1 = (*controlPoints)[last] - (*controlPoints)[last - 1];
|
||||
interval1 = (*intervalBoundaries)[last] - (*intervalBoundaries)[last - 1];
|
||||
result = 0.5f * (1 - auxData[last].x) * (delta1 / interval1);
|
||||
derivatives.push_back(result);
|
||||
}
|
||||
break;
|
||||
case HermiteModes::TBC:
|
||||
{
|
||||
assert(controlPoints->size() == auxData.size());
|
||||
int last = controlPoints->size() - 1;
|
||||
glm::vec3 delta1;
|
||||
glm::vec3 delta2;
|
||||
delta1 = (*controlPoints)[1] - (*controlPoints)[0];
|
||||
float interval1;
|
||||
float interval2;
|
||||
interval1 = (*intervalBoundaries)[1] - (*intervalBoundaries)[0];
|
||||
glm::vec3 result;
|
||||
//first
|
||||
result = 0.5f * (1 - auxData[0].x) * (1 + auxData[0].y) * (1 + auxData[0].z) * delta1 / interval1;
|
||||
derivatives.push_back(result);
|
||||
for (int i = 1; i < last; i++) {
|
||||
delta1 = (*controlPoints)[i + 1] - (*controlPoints)[i];
|
||||
delta2 = (*controlPoints)[i] - (*controlPoints)[i - 1];
|
||||
interval1 = (*intervalBoundaries)[i + 1] - (*intervalBoundaries)[i];
|
||||
interval2 = (*intervalBoundaries)[i] - (*intervalBoundaries)[i - 1];
|
||||
//last
|
||||
result = 0.5f * ((1 - auxData[i].x) * (1 + auxData[i].y) * (1 - auxData[i].z) * (delta1 / interval1) + (1 - auxData[i].x) * (1 - auxData[i].y) * (1 - auxData[i].z) * (delta2 / interval2));
|
||||
derivatives.push_back(result);
|
||||
//first
|
||||
result = 0.5f * ((1 - auxData[i].x) * (1 + auxData[i].y) * (1 + auxData[i].z) * (delta1 / interval1) + (1 - auxData[i].x) * (1 - auxData[i].y) * (1 - auxData[i].z) * (delta2 / interval2));
|
||||
derivatives.push_back(result);
|
||||
}
|
||||
delta1 = (*controlPoints)[last] - (*controlPoints)[last - 1];
|
||||
interval1 = (*intervalBoundaries)[last] - (*intervalBoundaries)[last - 1];
|
||||
//last
|
||||
result = 0.5f * ((1 - auxData[last].x) * (1 + auxData[last].y) * (1 - auxData[last].z) * (delta1 / interval1));
|
||||
derivatives.push_back(result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 Hermite::evaluateCubic(float t, float t1, float t2, glm::vec3 y1, glm::vec3 y2, glm::vec3 dy1, glm::vec3 dy2) {
|
||||
float interval = t2 - t1;
|
||||
float newX = (t - t1) / interval;
|
||||
return y1 * PHI0(newX) + dy1 * interval * PHI1(newX) + y2 * PSI0(newX) + dy2 * interval * PSI1(newX);
|
||||
}
|
||||
|
||||
glm::vec3 Hermite::evaluate(float at) {
|
||||
for (int i = 0; i < intervalBoundaries->size() - 1; i++)
|
||||
if ((*intervalBoundaries)[i] <= at && at <= (*intervalBoundaries)[i + 1])
|
||||
return evaluateCubic(at, (*intervalBoundaries)[i], (*intervalBoundaries)[i + 1], (*controlPoints)[i], (*controlPoints)[i + 1], derivatives[2 * i], derivatives[2 * i + 1]);
|
||||
return glm::vec3();
|
||||
}
|
||||
|
||||
glm::vec3 Hermite::derivate(float at) {
|
||||
return glm::vec3();
|
||||
}
|
||||
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