Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
AG Computergrafik
ss21cg3
Commits
4d885737
Commit
4d885737
authored
May 10, 2021
by
Bastian Krayer
Browse files
added solution 2
parent
8981fe07
Changes
9
Hide whitespace changes
Inline
Side-by-side
src/executables/BSplineSolution/BSpline.cpp
0 → 100644
View file @
4d885737
#include
"BSpline.h"
#include
<cmath>
BSpline
::
BSpline
(
std
::
vector
<
glm
::
vec3
>
cpoints
,
int
k
)
:
m_controlPoints
(
std
::
move
(
cpoints
)),
m_k
(
k
)
{}
BSpline
::~
BSpline
()
=
default
;
glm
::
vec3
BSpline
::
evaluate
(
float
t
)
{
// Aufgabe 5 (c)
// accumulate weighted points
glm
::
vec3
result
(
0.0
f
);
for
(
int
i
=
0
;
i
<
m_controlPoints
.
size
();
i
++
)
{
result
+=
coxDeBoor
(
t
,
i
,
m_k
)
*
m_controlPoints
[
i
];
}
return
result
;
}
float
BSpline
::
coxDeBoor
(
float
t
,
int
i
,
int
k
)
{
// Aufgabe 5 (d)
if
(
k
==
1
)
{
return
m_knotVector
[
i
]
<=
t
&&
t
<
m_knotVector
[
i
+
1
]
?
1.0
f
:
0.0
f
;
}
float
denom1
=
m_knotVector
[
i
+
k
-
1
]
-
m_knotVector
[
i
];
float
denom2
=
m_knotVector
[
i
+
k
]
-
m_knotVector
[
i
+
1
];
float
num1
=
(
t
-
m_knotVector
[
i
])
*
coxDeBoor
(
t
,
i
,
k
-
1
);
float
num2
=
(
m_knotVector
[
i
+
k
]
-
t
)
*
coxDeBoor
(
t
,
i
+
1
,
k
-
1
);
float
s1
=
std
::
abs
(
denom1
)
<
1E-7
?
0
:
num1
/
denom1
;
float
s2
=
std
::
abs
(
denom2
)
<
1E-7
?
0
:
num2
/
denom2
;
return
s1
+
s2
;
}
void
BSpline
::
setK
(
int
val
)
{
m_k
=
val
;
}
int
BSpline
::
getK
()
const
{
return
m_k
;
}
const
std
::
vector
<
glm
::
vec3
>&
BSpline
::
getVertices
()
{
return
m_vertices
;
}
const
std
::
vector
<
glm
::
vec3
>&
BSpline
::
getControlPoints
()
{
return
m_controlPoints
;
}
src/executables/BSplineSolution/BSpline.h
0 → 100644
View file @
4d885737
#ifndef BSPLINE_H
#define BSPLINE_H
#include
<glm/glm.hpp>
#include
<vector>
class
BSpline
{
public:
BSpline
(
std
::
vector
<
glm
::
vec3
>
cpoints
,
int
k
);
virtual
~
BSpline
();
virtual
bool
initialize
(
int
num
)
=
0
;
void
setK
(
int
val
);
int
getK
()
const
;
const
std
::
vector
<
glm
::
vec3
>&
getVertices
();
const
std
::
vector
<
glm
::
vec3
>&
getControlPoints
();
protected:
float
coxDeBoor
(
float
t
,
int
i
,
int
k
);
glm
::
vec3
evaluate
(
float
t
);
std
::
vector
<
glm
::
vec3
>
m_controlPoints
;
std
::
vector
<
glm
::
vec3
>
m_vertices
;
std
::
vector
<
float
>
m_knotVector
;
int
m_k
=
0
;
};
#endif
\ No newline at end of file
src/executables/BSplineSolution/CMakeLists.txt
0 → 100644
View file @
4d885737
cmake_minimum_required
(
VERSION 3.1
)
include
(
${
CMAKE_MODULE_PATH
}
/DefaultExecutable.cmake
)
\ No newline at end of file
src/executables/BSplineSolution/OpenBSpline.cpp
0 → 100644
View file @
4d885737
#include
"OpenBSpline.h"
// for std::iota
#include
<numeric>
// for std::is_sorted
#include
<algorithm>
bool
OpenBSpline
::
initialize
(
int
num
)
{
auto
n
=
m_controlPoints
.
size
();
// check correct size
if
(
m_knotVector
.
size
()
!=
m_k
+
n
)
{
return
false
;
}
// check if values are in increasing order
// alternatively, loop yourself
if
(
!
std
::
is_sorted
(
m_knotVector
.
begin
(),
m_knotVector
.
end
()))
{
return
false
;
}
// min param
float
min_t
=
m_knotVector
[
m_k
-
1
];
float
max_t
=
m_knotVector
[
n
];
float
d_t
=
max_t
-
min_t
;
// generate points
m_vertices
.
resize
(
num
);
for
(
int
i
=
0
;
i
<
num
;
i
++
)
{
// t value sampled in valid interval
auto
t
=
min_t
+
d_t
*
static_cast
<
float
>
(
i
)
/
static_cast
<
float
>
(
num
);
m_vertices
[
i
]
=
evaluate
(
t
);
}
return
true
;
}
OpenBSpline
::
OpenBSpline
(
std
::
vector
<
glm
::
vec3
>
cpoints
,
int
k
,
int
num
)
:
BSpline
(
std
::
move
(
cpoints
),
k
)
{
// number of knots in knot vector is n + k
auto
n
=
m_controlPoints
.
size
();
auto
nk
=
n
+
k
;
m_knotVector
.
resize
(
nk
);
// first n values are 0
std
::
fill
(
m_knotVector
.
begin
(),
m_knotVector
.
begin
()
+
k
,
0
);
std
::
iota
(
m_knotVector
.
begin
()
+
k
,
m_knotVector
.
begin
()
+
n
,
1
);
std
::
fill
(
m_knotVector
.
begin
()
+
n
,
m_knotVector
.
end
(),
n
-
k
+
1
);
initialize
(
num
);
}
src/executables/BSplineSolution/OpenBSpline.h
0 → 100644
View file @
4d885737
#ifndef OPENBSPLINE_H
#define OPENBSPLINE_H
#include
"BSpline.h"
class
OpenBSpline
:
public
BSpline
{
public:
OpenBSpline
(
std
::
vector
<
glm
::
vec3
>
cpoints
,
int
k
,
int
num
);
bool
initialize
(
int
num
)
override
;
};
#endif // OPENBSPLINE_H
src/executables/BSplineSolution/PeriodicBSpline.cpp
0 → 100644
View file @
4d885737
#include
"PeriodicBSpline.h"
// for std::iota
#include
<numeric>
// for std::is_sorted
#include
<algorithm>
PeriodicBSpline
::
PeriodicBSpline
(
std
::
vector
<
glm
::
vec3
>
cpoints
,
int
k
,
int
num
)
:
BSpline
(
std
::
move
(
cpoints
),
k
)
{
// Aufgabe 5 (a)
// number of knots in knot vector is n + k
auto
n
=
m_controlPoints
.
size
();
auto
nk
=
n
+
k
;
m_knotVector
.
resize
(
nk
);
// periodic b-spline has increasing number of values
// std::iota fills vector with increasing values starting at the last
// argument.
// Alternatively loop over size
std
::
iota
(
m_knotVector
.
begin
(),
m_knotVector
.
end
(),
0
);
initialize
(
num
);
}
PeriodicBSpline
::~
PeriodicBSpline
()
=
default
;
bool
PeriodicBSpline
::
initialize
(
int
num
)
{
// Aufgabe 5 (b)
auto
n
=
m_controlPoints
.
size
();
// check correct size
if
(
m_knotVector
.
size
()
!=
m_k
+
n
)
{
return
false
;
}
// check if values are in increasing order
// alternatively, loop yourself
if
(
!
std
::
is_sorted
(
m_knotVector
.
begin
(),
m_knotVector
.
end
()))
{
return
false
;
}
// min param
float
min_t
=
m_knotVector
[
m_k
-
1
];
float
max_t
=
m_knotVector
[
n
];
float
d_t
=
max_t
-
min_t
;
// generate points
m_vertices
.
resize
(
num
);
for
(
int
i
=
0
;
i
<
num
;
i
++
)
{
// t value sampled in valid interval
auto
t
=
min_t
+
d_t
*
static_cast
<
float
>
(
i
)
/
static_cast
<
float
>
(
num
);
m_vertices
[
i
]
=
evaluate
(
t
);
}
return
true
;
}
\ No newline at end of file
src/executables/BSplineSolution/PeriodicBSpline.h
0 → 100644
View file @
4d885737
#ifndef PERIODICBSPLINE_H
#define PERIODICBSPLINE_H
#include
"BSpline.h"
class
PeriodicBSpline
:
public
BSpline
{
public:
PeriodicBSpline
(
std
::
vector
<
glm
::
vec3
>
cpoints
,
int
k
,
int
num
);
~
PeriodicBSpline
()
override
;
bool
initialize
(
int
num
)
override
;
};
#endif
src/executables/BSplineSolution/dependencies.txt
0 → 100644
View file @
4d885737
CVK_2
\ No newline at end of file
src/executables/BSplineSolution/main.cpp
0 → 100644
View file @
4d885737
#include
"OpenBSpline.h"
#include
"PeriodicBSpline.h"
#include
<CVK_2/CVK_Framework.h>
#include
<glad/glad.h>
#include
<memory>
constexpr
int
width
=
800
;
// window width
constexpr
int
height
=
800
;
// window height
class
ExBSplineSolution
:
public
CVK
::
GlfwBase
{
public:
ExBSplineSolution
();
~
ExBSplineSolution
();
// run the actual loop and display
void
display
();
// render the spline
void
renderSpline
(
BSpline
&
spline
);
// callback for key input
static
void
keyfun
(
GLFWwindow
*
window
,
int
key
,
int
,
int
action
,
int
);
private:
// number of vertices
int
numSamples
=
1000
;
// order
int
k
=
5
;
int
drawType
=
0
;
// render parameters
GLint
m_colorHandle
=
0
;
GLuint
m_vbos
[
2
]{};
GLuint
m_vaoHandle
=
0
;
std
::
unique_ptr
<
CVK
::
ShaderSet
>
m_shaderProgram
;
};
int
main
()
{
// Construct and display
ExBSplineSolution
demo
;
demo
.
display
();
return
0
;
}
// Implementation
ExBSplineSolution
::
ExBSplineSolution
()
{
m_window
=
glfwCreateWindow
(
width
,
height
,
"BSpline"
,
nullptr
,
nullptr
);
glfwSetWindowPos
(
m_window
,
600
,
50
);
glfwMakeContextCurrent
(
m_window
);
glfwSetWindowUserPointer
(
m_window
,
this
);
glfwSetKeyCallback
(
m_window
,
keyfun
);
// init opengl
if
(
!
gladLoadGLLoader
((
GLADloadproc
)
glfwGetProcAddress
))
{
std
::
cerr
<<
"Failed to initialize OpenGL context"
<<
std
::
endl
;
throw
std
::
runtime_error
(
"Failed to initialize OpenGL context"
);
}
glClearColor
(
1
,
1
,
1
,
1
);
// compile a shader program
m_shaderProgram
=
std
::
make_unique
<
CVK
::
ShaderSet
>
(
VERTEX_SHADER_BIT
|
FRAGMENT_SHADER_BIT
,
std
::
vector
<
std
::
string
>
{
CVK
::
State
::
getInstance
()
->
getShaderPath
()
+
"/BSplines/bsplines.vert"
,
CVK
::
State
::
getInstance
()
->
getShaderPath
()
+
"/BSplines/bsplines.frag"
});
// use the shader program
m_shaderProgram
->
useProgram
();
m_colorHandle
=
glGetUniformLocation
(
m_shaderProgram
->
getProgramID
(),
"color"
);
glGenVertexArrays
(
1
,
&
m_vaoHandle
);
glBindVertexArray
(
m_vaoHandle
);
glGenBuffers
(
2
,
m_vbos
);
}
ExBSplineSolution
::~
ExBSplineSolution
()
{
glDeleteBuffers
(
2
,
m_vbos
);
glDeleteVertexArrays
(
1
,
&
m_vaoHandle
);
}
void
ExBSplineSolution
::
display
()
{
// controlpoints
std
::
vector
<
glm
::
vec3
>
cpoints
;
// create control points
cpoints
.
emplace_back
(
-
0.5
f
,
-
0.25
f
,
0.0
f
);
cpoints
.
emplace_back
(
0.0
f
,
0.5
f
,
0.0
f
);
cpoints
.
emplace_back
(
0.5
f
,
-
0.25
f
,
0.0
f
);
cpoints
.
emplace_back
(
0.75
f
,
-
0.75
f
,
0.0
f
);
cpoints
.
emplace_back
(
-
0.75
f
,
-
0.75
f
,
0.0
f
);
PeriodicBSpline
pSpline
(
cpoints
,
k
,
numSamples
);
OpenBSpline
oSpline
(
cpoints
,
k
,
numSamples
);
// render stuff
// Renderer lives only in this block and will clean up when it is
// destroyed
while
(
!
glfwWindowShouldClose
(
m_window
))
{
glClear
(
GL_COLOR_BUFFER_BIT
|
GL_DEPTH_BUFFER_BIT
);
if
(
drawType
==
0
)
{
renderSpline
(
pSpline
);
}
else
{
renderSpline
(
oSpline
);
}
// show what's been drawn
glfwSwapBuffers
(
m_window
);
glfwPollEvents
();
}
}
void
ExBSplineSolution
::
keyfun
(
GLFWwindow
*
window
,
int
key
,
int
,
int
action
,
int
)
{
// Since glfw callbacks come from C, we can only pass static member
// functions. But at the beginning, we store a pointer to our object
// with this window and we can retrieve it. "demo" effectively acts as
// "this" here
auto
demo
=
static_cast
<
ExBSplineSolution
*>
(
glfwGetWindowUserPointer
(
window
));
if
(
key
==
GLFW_KEY_N
&&
action
==
GLFW_PRESS
)
{
demo
->
drawType
=
(
demo
->
drawType
+
1
)
%
2
;
}
}
void
ExBSplineSolution
::
renderSpline
(
BSpline
&
spline
)
{
glm
::
vec3
black
=
glm
::
vec3
(
0.0
f
,
0.0
f
,
0.0
f
);
glm
::
vec3
red
=
glm
::
vec3
(
1.0
f
,
0.0
f
,
0.0
f
);
// draw control points
glPointSize
(
15.0
f
);
glUniform3fv
(
m_colorHandle
,
1
,
glm
::
value_ptr
(
black
));
glBindBuffer
(
GL_ARRAY_BUFFER
,
m_vbos
[
0
]);
glBufferData
(
GL_ARRAY_BUFFER
,
sizeof
(
glm
::
vec3
)
*
spline
.
getControlPoints
().
size
(),
spline
.
getControlPoints
().
data
(),
GL_DYNAMIC_DRAW
);
glEnableVertexAttribArray
(
0
);
glVertexAttribPointer
(
0
,
3
,
GL_FLOAT
,
GL_FALSE
,
0
,
nullptr
);
glDrawArrays
(
GL_POINTS
,
0
,
spline
.
getControlPoints
().
size
());
// draw curve points
glPointSize
(
5.0
f
);
glUniform3fv
(
m_colorHandle
,
1
,
glm
::
value_ptr
(
red
));
glBindBuffer
(
GL_ARRAY_BUFFER
,
m_vbos
[
1
]);
glBufferData
(
GL_ARRAY_BUFFER
,
sizeof
(
glm
::
vec3
)
*
spline
.
getVertices
().
size
(),
spline
.
getVertices
().
data
(),
GL_STATIC_DRAW
);
glEnableVertexAttribArray
(
0
);
glVertexAttribPointer
(
0
,
3
,
GL_FLOAT
,
GL_FALSE
,
0
,
nullptr
);
glDrawArrays
(
GL_LINE_STRIP
,
0
,
spline
.
getVertices
().
size
());
// unbind the VBO, we don't need it anymore
glBindBuffer
(
GL_ARRAY_BUFFER
,
0
);
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment