Skip to content
Snippets Groups Projects
Commit 42c33d22 authored by 영제 임's avatar 영제 임
Browse files

exercise

parents
No related branches found
No related tags found
No related merge requests found
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <vector>
#include "toys.h"
#include <glm/gtc/type_ptr.hpp>
#include "j3a.hpp"
#include <math.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
using namespace glm;
const float PI = 3.141592;
vec3 lightPos = vec3(3, 5, 5);
vec3 lightInt = vec3(1, 1, 1);
vec3 color = vec3(1, .3, 0);
vec3 ambInt = vec3(0.1, 0.1, 0.1);
float shin = 20;
void render(GLFWwindow* window);
void init();
float clearB = .0f;
float theta = .0f;
float phi = .0f;
float fovy = 60;
float cameraDistance = 1; //perspective쓸때 사용한다
float triangleSize = 0.3;
//mat3 rotation;
Program program;
Program shadowProg;
GLuint vertbuf = 0;//데이터를 드라이브에서 받아와서 저장
GLuint normbuf = 0;
GLuint tcoordbuf = 0;
GLuint vertexArray = 0;
GLuint tribuf = 0;
GLuint texID = 0;
GLuint bumpID = 0;
GLuint fbo = 0;
GLuint shadowTex = 0;
GLuint shadowDepth = 0;
vec3 cameraPosition = vec3(0, 0, 5);
double oldX;
double oldY;
void cursorCallback(GLFWwindow* window, double xpos, double ypos) {
int width, height;
glfwGetWindowSize(window, &width, &height);
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1)) {
theta -= (xpos - oldX) / width * PI; //차이만큼 경도를 움직여준다 움직이는 범위가 윈도우크기만큼
phi -= (ypos - oldY) / height * PI;
//printf("%0.2f ", phi);
//if (phi < (-PI / 2 + 0.01) / (PI)) phi = (-PI / 2 + 0.01) / (PI);
//if (phi > (PI / 2 - 0.01) / (PI)) phi = (PI / 2 - 0.01) / (PI);
}
oldX = xpos;
oldY = ypos;
}
void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) {
fovy = fovy * pow(1.01, -yoffset); //스크롤의 위 아래
//if (fovy < 10) fovy = 10;
//if (fovy > 170) fovy = 170;
//cameraDistance = cameraDistance * pow(1.01, -yoffset);
}
//if를 설정. 범위를 벗어날 경우 변화를 주지 말아야 한다.
int main(void) {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); //glfw설정
glfwWindowHint(GLFW_SAMPLES, 8);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(800, 800, "yeong_jae", nullptr, nullptr);
glfwSetCursorPosCallback(window, cursorCallback); //우리함수를 필요할 때 불러 주는 것, 윈도우에 붙이는 것
glfwSetScrollCallback(window, scrollCallback);
glfwMakeContextCurrent(window); //컨텍스트를 통해 접근 가능
glewInit(); //초기설정
//glfwSwapInterval(1); //10이면 화면이 10번 refresh될 떄마다 1번 그려라,
init();
while (!glfwWindowShouldClose(window)) {
render(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
}
const int shadowMapSize = 1024;
void init() {
glGenTextures(1, &shadowTex);
glBindTexture(GL_TEXTURE_2D, shadowTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, shadowMapSize, shadowMapSize, 0, GL_RGB, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glGenTextures(1, &shadowDepth);
glBindTexture(GL_TEXTURE_2D, shadowDepth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, shadowMapSize, shadowMapSize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, shadowTex, 0);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadowDepth, 0);
GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, drawBuffers);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) printf("FBO Error\n");
glBindFramebuffer(GL_FRAMEBUFFER, GL_NONE);
program.loadShaders("shader.vert", "shader.frag"); //vec3 정의
shadowProg.loadShaders("shadow.vert", "shadow.frag"); //vec3 정의
loadJ3A("C:\\Users\\iyj01\\source\\MyProject\\OpenGLTest\\OpenGLTest\\dwarf.j3a");
stbi_set_flip_vertically_on_load(true);
int w = 0, h = 0, n = 0;
void* buf = stbi_load(("C:\\Users\\iyj01\\source\\MyProject\\OpenGLTest\\OpenGLTest\\" + diffuseMap[0]).c_str(), &w, &h, &n, 4);
glGenTextures(1, &texID);
glBindTexture(GL_TEXTURE_2D, texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(buf);
buf = stbi_load(("C:\\Users\\iyj01\\source\\MyProject\\OpenGLTest\\OpenGLTest\\" + bumpMap[0]).c_str(), &w, &h, &n, 4);
glGenTextures(1, &bumpID);
glBindTexture(GL_TEXTURE_2D, bumpID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(buf);
glGenBuffers(1, &vertbuf);//1개 만든다
glBindBuffer(GL_ARRAY_BUFFER, vertbuf);
glBufferData(GL_ARRAY_BUFFER, nVertices[0] * sizeof(glm::vec3), vertices[0], GL_STATIC_DRAW); //vertex의 개수와 좌표가 이미 있다
glGenBuffers(1, &normbuf);//1개 만든다
glBindBuffer(GL_ARRAY_BUFFER, normbuf);
glBufferData(GL_ARRAY_BUFFER, nVertices[0] * sizeof(glm::vec3), normals[0], GL_STATIC_DRAW);
glGenBuffers(1, &tcoordbuf);//1개 만든다, vertex shader가 받는다
glBindBuffer(GL_ARRAY_BUFFER, tcoordbuf);
glBufferData(GL_ARRAY_BUFFER, nVertices[0] * sizeof(glm::vec2), texCoords[0], GL_STATIC_DRAW);
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray); //타겟을 주지 않아도 된다. 0번 자리에 들어가야한다고 표시를 해줘야한다.
glEnableVertexAttribArray( 0 ); //bind되어서 vertexArray안써줘도된다, vertaxarray의 0번 자리
glBindBuffer(GL_ARRAY_BUFFER, vertbuf); //혹시 모르니까 다시 묶어줌
glVertexAttribPointer(0, 3, GL_FLOAT, 0, 0, 0);//0번 자리에 하나의 단위의 사이즈, 형태. 묶인 vertexArray에 vertbuf를 연결
glEnableVertexAttribArray(1); //bind되어서 vertexArray안써줘도된다, vertaxarray의 0번 자리
glBindBuffer(GL_ARRAY_BUFFER, normbuf); //혹시 모르니까 다시 묶어줌
glVertexAttribPointer(1, 3, GL_FLOAT, 0, 0, 0);//0번 자리에 하나의 단위의 사이즈, 형태. 묶인 vertexArray에 normbuf를 연결
//1번 자리에 vec3
glEnableVertexAttribArray(2); //bind되어서 vertexArray안써줘도된다, vertaxarray의 0번 자리
glBindBuffer(GL_ARRAY_BUFFER, tcoordbuf); //혹시 모르니까 다시 묶어줌
glVertexAttribPointer(2, 2, GL_FLOAT, 0, 0, 0);//0번 자리에 하나의 단위의 사이즈, 형태. 묶인 vertexArray에 tcoordbuf를 연결
//2번 자리에 vec2
//삼각형의 정보를 담기위한 처리
glGenBuffers(1, &tribuf);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tribuf); //arraybuffer가 아니다.
glBufferData(GL_ELEMENT_ARRAY_BUFFER, nTriangles[0] * sizeof(glm::u32vec3), triangles[0], GL_STATIC_DRAW); //삼각형의 개수와 좌표가 이미 있다
}
void render(GLFWwindow* window) { //그리기는 render에서 한다
glEnable(GL_DEPTH_TEST);
GLuint loc;
int width, height;
glfwGetFramebufferSize(window, &width, &height);
mat4 modelMat = mat4(1);
mat4 shadowMVP = ortho(-2.f, 2.f, -2.f, 2.f, 0.01f, 10.f)
* lookAt(lightPos, vec3(0), vec3(0, 1, 0))
* modelMat;
glUseProgram(shadowProg.programID);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0, 0, shadowMapSize, shadowMapSize);
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
loc = glGetUniformLocation(shadowProg.programID, "shadowMVP"); //shader에 보내는 과정(uniform을)
glUniformMatrix4fv(loc, 1, false, glm::value_ptr(shadowMVP));
glBindVertexArray(vertexArray); //묶어준다
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tribuf);
glDrawElements(GL_TRIANGLES, nTriangles[0] * 3, GL_UNSIGNED_INT, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
vec3 cameraPos = vec3(rotate(theta, vec3(0, 1, 0)) * rotate(phi, vec3(1, 0, 0)) * vec4(cameraPosition, 1)); //cameraPosition* cameraDistance
//세타는 y축 기준으로 돈다
mat4 viewMat = lookAt(cameraPos, vec3(0, 0, 0), vec3(0, 1, 0));
mat4 projMat = perspective(fovy * PI / 180, width / (float)height, 0.1f, 100.f); //aspect는 비율
glViewport(0, 0, width, height); //전체를 다 쓴다
glClearColor(0, 0, 0.2, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //지우려는 버퍼의 비트 전달
glEnable(GL_DEPTH_TEST);
glEnable(GL_FRAMEBUFFER_SRGB);
glUseProgram(program.programID);
loc = glGetUniformLocation(program.programID, "modelMat"); //shader에 보내는 과정(uniform을)
glUniformMatrix4fv(loc, 1, false, glm::value_ptr(modelMat));
loc = glGetUniformLocation(program.programID, "viewMat");
glUniformMatrix4fv(loc, 1, false, glm::value_ptr(viewMat));
loc = glGetUniformLocation(program.programID, "projMat");
glUniformMatrix4fv(loc, 1, false, glm::value_ptr(projMat));
loc = glGetUniformLocation(program.programID, "lightPos");
glUniform3fv(loc, 1, glm::value_ptr(lightPos));
loc = glGetUniformLocation(program.programID, "lightInt");
glUniform3fv(loc, 1, glm::value_ptr(lightInt));
loc = glGetUniformLocation(program.programID, "ambInt");
glUniform3fv(loc, 1, glm::value_ptr(ambInt));
loc = glGetUniformLocation(program.programID, "color");
glUniform3fv(loc, 1, glm::value_ptr(diffuseColor[0])); //j3a파일에 이미 색깔이 존재한다
loc = glGetUniformLocation(program.programID, "specularColor");
glUniform3fv(loc, 1, glm::value_ptr(specularColor[0])); //j3a파일에 이미 색깔이 존재한다
loc = glGetUniformLocation(program.programID, "shininess");
glUniform1f(loc, shininess[0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texID);
loc = glGetUniformLocation(program.programID, "colorTexture");
glUniform1i(loc, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, bumpID);
loc = glGetUniformLocation(program.programID, "bumpTexture");
glUniform1i(loc, 1);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, shadowTex);
loc = glGetUniformLocation(program.programID, "shadowMap");
glUniform1i(loc, 2);
loc = glGetUniformLocation(program.programID, "shadowMVP");
glUniformMatrix4fv(loc, 1, false, value_ptr(shadowMVP));
loc = glGetUniformLocation(program.programID, "cameraPos");
glUniform3fv(loc, 1, glm::value_ptr(cameraPos));
glBindVertexArray(vertexArray); //묶어준다
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tribuf);
glDrawElements(GL_TRIANGLES, nTriangles[0] * 3, GL_UNSIGNED_INT, 0);//사용해서 primitive를 그린다, 3은 삼각형을 이루는 정점의 갯수
glfwSwapBuffers(window);
}
/*
loc = glGetUniformLocation(program.programID, "transf");
rotation = mat3(cos(theta * PI / 180), -sin(theta * PI / 180), 0, sin(theta * PI / 180), cos(theta * PI / 180), 0, 0, 0, 1);
mat3 transf = rotation;
glUniformMatrix3fv(loc, 1, false, value_ptr(transf));
*/
\ No newline at end of file
main.cpp 0 → 100644
//
// main.cpp
// CurveInter
//
// Created by Hyun Joon Shin on 2021/03/24.
//
#include <iostream>
#include <JGL/JGL.hpp>
#include <JGL/JGL_Window.hpp>
#include <JGL/JGL_Widget.hpp>
#include <JGL/JGL_Options.hpp>
#include <JGL/JGL_Toolbar.hpp>
#include <JGL/JGL_Aligner.hpp>
enum {
LAGLANGIAN,
LINEAR,
BEZIER,
CATMULL,
BSPLINE,
NATURAL,
};
enum {
DRAW_LINES,
DRAW_DOTS,
};
int curveType = LINEAR;
int drawType = DRAW_LINES;
bool closed = false;
std::vector<glm::vec2> srcPts;
std::vector<glm::vec2> samplePts;
glm::vec2 evaluateCurve( int curveType, const std::vector<glm::vec2>& srcPts, bool closed, size_t k, float t ) {//p는 k번째에서 0부터 1까지
using std::vector;
using glm::vec2;
glm::vec2 ret(0,0);
switch( curveType ) {
case LAGLANGIAN: { //local controllability가 없다(다른 곳에 영향을 준다)/ convexhull, variation diminishing만족x
float T = k+t;
for( auto i=0; i<srcPts.size(); i++ ) {
float L = 1;
for( auto j=0; j<srcPts.size(); j++ ) {
if( j!=i ) {
L/=(i-j);
L*=T-j;
}
}
ret+=L*srcPts[i];
}
} break;
case CATMULL: //dot으로 보면 속도가 나온다
{
glm::vec2 v0(0), v1(0);
if (k > 0) {
v0 = (srcPts[k + 1] - srcPts[k - 1]) / 2.f;
}
else {//행렬을 세로로 쓴다
glm::mat3 A = { 0,1,4,0,1,2,1,1,1 };
{
glm::vec3 b = { srcPts[0].x, srcPts[1].x , srcPts[2].x };
glm::vec3 x = glm::inverse(A) * b; //이 점을 만족하는 parabola(2차 포물선)가 있었을 것. 이걸 미분
v0.x = x.y;
}
glm::vec3 b = { srcPts[0].y, srcPts[1].y , srcPts[2].y };
glm::vec3 x = glm::inverse(A) * b; //이 점을 만족하는 parabola(2차 포물선)가 있었을 것. 이걸 미분
v0.y = x.y;
}
if (k < srcPts.size() - 2) {
v1 = (srcPts[k + 2] - srcPts[k]) / 2.f;
}
glm::vec2 c0 = srcPts[k] + v0 / 3.f;
glm::vec2 c1 = srcPts[k + 1] - v1 / 3.f;
return (1 - t) * (1 - t) * (1 - t) * srcPts[k] + 3 * t * (1 - t) * (1 - t) * c0
+ 3 * t * t * (1 - t) * c1 + t * t * t * srcPts[k + 1];
}break;
case BEZIER:
{ //p가 0부터 1일때 까지만
if (k == 0) { //k가 0일 0, 1, 2, 3번만 만든다
return (1 - t) * (1 - t) * (1 - t) * srcPts[0] + 3 * t * (1 - t) * (1 - t) * srcPts[1]
+ 3 * t * t * (1 - t) * srcPts[2] + t * t * t * srcPts[3];
}
else {
return srcPts[3];
}
}break;
case NATURAL:
{
size_t N = srcPts.size();
//Dx = b - Lx - Ux
//한개의 element만 생각
//4[i,i]*x[i] = b[i] - x[i+1] - x[i-1] if i!=0 or i!=N-1
vector<float> Dx;
vector<float> Dy;
{
vector<float> D0(N, 0); //점이 N개가 있고 선이 N-1개 우선 시작은 다 0으로
vector<float> D1(N, 0);
for (int i = 0; i < 10; i++) { //diagonal이 많이 dominant할 수록 다른거에 비해서 크면 적은 반복으로도 가능하다
vector<float>& x_n = (i % 2 == 0) ? D0 : D1;
vector<float>& x_n1 = (i % 2 == 0) ? D1 : D0;
for (int j = 1; j < x_n.size() - 1; j++) {
x_n1[j] = (3 * (srcPts[j + 1].x - srcPts[j - 1].x) - x_n[j + 1] - x_n[j - 1]) / 4; //이게 b에 해당한다
}
}
Dx = D0;
}
{
vector<float> D0(N, 0); //점이 N개가 있고 선이 N-1개 우선 시작은 다 0으로
vector<float> D1(N, 0);
for (int i = 0; i < 10; i++) {
vector<float>& x_n = (i % 2 == 0) ? D0 : D1;
vector<float>& x_n1 = (i % 2 == 0) ? D1 : D0;
for (int j = 1; j < x_n.size() - 1; j++) {
x_n1[j] = (3 * (srcPts[j + 1].y - srcPts[j - 1].y) - x_n[j + 1] - x_n[j - 1]) / 4; //이게 b에 해당한다
}
}
Dy = D0;
}
vec2 a = srcPts[k];
vec2 b = vec2(Dx[k], Dy[k]);
vec2 c = 3.f * (srcPts[k + 1] - srcPts[k]) - 2.f * vec2(Dx[k], Dy[k]) - vec2(Dx[k + 1], Dy[k + 1]);
vec2 d = 2.f * (srcPts[k] - srcPts[k + 1]) + vec2(Dx[k], Dy[k]) + vec2(Dx[k + 1], Dy[k + 1]);
return a + b * t + c * t * t + d * t * t * t;
}break;
case LINEAR : //convexhull, variation diminishing, affine invariance을 만족한다. C0 continuity, local control 가능
default: {
ret = (srcPts[k+1]-srcPts[k])*t + srcPts[k];
}
}
return ret;
}
void updateCurve( int curveType, const std::vector<glm::vec2>& srcPts, bool closed ) {
samplePts.clear();
for( auto i=0; i<srcPts.size()-1; i++ ) {
for( float t = 0; t<1; t+=0.02 ) {
samplePts.push_back( evaluateCurve( curveType, srcPts, closed, i, t ) );
}
}
if( closed ) {
for( float t = 0; t<1; t+=0.02 ) {
samplePts.push_back( evaluateCurve( curveType, srcPts, closed, srcPts.size()-1, t ) );
}
}
else
samplePts.push_back( evaluateCurve( curveType, srcPts, closed, srcPts.size()-2, 1 ) );
}
#include <JGL/nanovg/nanovg.h>
struct CurveWidget : JGL::Widget {
CurveWidget(float x, float y, float w, float h, const std::string& title = "" )
: JGL::Widget(x,y,w,h,title){}
virtual void drawBox(NVGcontext* vg, const glm::rect& r) override {
nvgSave(vg);
nvgBeginPath( vg );
nvgRect( vg, r.x, r.y, r.w, r.h );
nvgFillColor( vg, nvgRGBAf(0,0,0,1));
nvgFill( vg );
nvgRestore(vg);
}
virtual void drawContents(NVGcontext* vg, const glm::rect& r, int align ) override {
nvgSave(vg);
if( drawType == DRAW_LINES ) {
nvgBeginPath( vg );
nvgMoveTo( vg, samplePts[0].x, samplePts[0].y );
for( auto i=1; i<samplePts.size(); i++ ) {
nvgLineTo( vg, samplePts[i].x, samplePts[i].y );
}
nvgStrokeColor(vg, nvgRGBAf(0,.8f,1,1));
nvgStrokeWidth(vg, 2);
nvgStroke( vg );
}
else {
nvgFillColor(vg, nvgRGBAf(0,1,.3f,1));
nvgBeginPath( vg );
for( auto i=0; i<samplePts.size(); i++ ) {
nvgCircle(vg, samplePts[i].x, samplePts[i].y, 1);
}
nvgFill( vg );
}
for( auto i=0; i<srcPts.size(); i++ )
if( i!= underPt ) {
nvgBeginPath( vg );
nvgCircle( vg, srcPts[i].x, srcPts[i].y, 5 );
nvgFillColor( vg, nvgRGBAf(1,1,0,.8f));
nvgFill( vg );
}
if( underPt>=0 ) {
nvgBeginPath( vg );
nvgCircle( vg, srcPts[underPt].x, srcPts[underPt].y, 5 );
nvgFillColor( vg, nvgRGBAf(1,.1f,0,.8f));
nvgFill( vg );
}
nvgRestore(vg);
}
virtual bool handle( int event ) override {
glm::vec2 pt = JGL::_JGL::eventPt();
switch( event ) {
case JGL::EVENT_MOVE : {
int oldPt = underPt;
underPt = -1;
for( auto i=0; i<srcPts.size(); i++ ) {
if( length(pt-srcPts[i])<6 )
underPt = i;
}
if( underPt!= oldPt ) {
redraw();
}
}break;
case JGL::EVENT_PUSH : {
if( underPt>=0 )
ptOffset = srcPts[underPt]-pt;
}break;
case JGL::EVENT_DRAG : {
if( underPt>=0 ) {
srcPts[underPt] = pt+ptOffset;
updateCurve( curveType, srcPts, closed );
redraw();
}
}break;
}
return true;
}
int underPt = -1;
glm::vec2 ptOffset = glm::vec2(0);
};
using namespace JGL;
CurveWidget* curveWidget;
void curveTypeCallback(Widget* w, void* ud ) {
curveType = ((Options*)w)->value();
//if (curveType == NATURAL) closed = true; else closed = false;
updateCurve(curveType, srcPts, closed);
curveWidget->redraw();
}
void drawTypeCallback(Widget* w, void* ud ) {
drawType = ((Options*)w)->value();
curveWidget->redraw();
}
int main(int argc, const char * argv[]) {
Window* window = new Window(640,480,"Curves");
window->alignment(ALIGN_ALL);
Aligner* aligner = new Aligner(0,0,window->w(), window->h());
aligner->type(Aligner::VERTICAL);
aligner->alignment(ALIGN_ALL);
Toolbar* toolbar = new Toolbar(0,0,window->w(), _size_toolbar_height() );
Options* curveTypes = new Options(0,0,200,_size_button_height() );
curveTypes->add("Lagrangian");
curveTypes->add("Linear");
curveTypes->add("Bezier");
curveTypes->add("Catmull");
curveTypes->add("Bspline");
curveTypes->add("Natural Spline");
curveTypes->value(curveType);
curveTypes->callback( curveTypeCallback );
Options* drawType = new Options(0,0,200,_size_button_height() );
drawType->add("Lines");
drawType->add("Dots");
drawType->value(::drawType);
drawType->callback( drawTypeCallback );
toolbar->end();
curveWidget = new CurveWidget(0,0,window->w(), window->h()-toolbar->h());
aligner->resizable( curveWidget );
aligner->end();
for( auto i=0; i<9; i++ ) {
srcPts.push_back(glm::vec2((i*0.1+0.1)*curveWidget->w(),curveWidget->h()/2));
}
updateCurve(curveType,srcPts,closed);
window->show();
_JGL::run();
return 0;
}
main2.cpp 0 → 100644
//
// main.cpp
// CurveInter
//
// Created by Hyun Joon Shin on 2021/03/24.
//
#include <iostream>
#include <JGL/JGL.hpp>
#include <JGL/JGL_Window.hpp>
#include <JGL/JGL_Widget.hpp>
#include <JGL/JGL_Options.hpp>
#include <JGL/JGL_Toolbar.hpp>
#include <JGL/JGL_Aligner.hpp>
#include <Eigen/Dense>
enum {
LAGLANGIAN,
LINEAR,
BEZIER,
CATMULL,
CATMULL2,
BSPLINE,
NATURAL,
CLOSED,
};
enum {
DRAW_LINES,
DRAW_DOTS,
};
int curveType;
int drawType;
std::vector<glm::vec2> srcPts;
bool pointsDirty = true;
glm::vec2 evaluateCurve( size_t k, float t ) {
glm::vec2 ret(0,0);
switch( curveType ) {
case LAGLANGIAN: {
float T = k+t;
for( auto i=0; i<srcPts.size(); i++ ) {
float L = 1;
for( auto j=0; j<srcPts.size(); j++ ) {
if( j!=i ) {
L/=(i-j);
L*=T-j;
}
}
ret+=L*srcPts[i];
}
} break;
case BEZIER: {
if( k>2 )
ret = srcPts[k];
else {
float T = (k+t)/3;
ret = (1-T)*(1-T)*(1-T)*srcPts[0]
+3*(1-T)*(1-T)*T*srcPts[1]
+3*(1-T)*T*T*srcPts[2]
+T*T*T*srcPts[3];
}
} break;
case CATMULL: {
glm::vec2 p0, p1, p2, p3;
glm::vec2 v0(0), v1(0);
if(k>0) // Ω√¿€¡° ¿Ã¿¸ø° ¡°¿Ã 毿ª ºˆ ¿÷¿∏¥œ±Ò
{//v0 = (srcPts[k + 1] - srcPts[k - 1]) / 2.f;
glm::mat3 A(1, 0, 1, -1, 0, 1, 1, 1, 1);//t-1, 1, t+1
glm::vec3 bx = glm::vec3(srcPts[k - 1].x, srcPts[k].x, srcPts[k + 1].x);
glm::vec3 by = glm::vec3(srcPts[k - 1].y, srcPts[k].y, srcPts[k + 1].y);//2¬˜ø¯¿Ã¥œ±Ò
glm::vec3 xx = glm::inverse(A) * bx;
glm::vec3 xy = glm::inverse(A) * by;
v0 = glm::vec2(xx.y, xy.y); // k 일 때 이므로 행렬을 보면 t=0
}
else {//∫∏≈Î catmull¿∫ tangent 0¿∏∑Œ Ω√¿€«ÿº≠ √µ√µ»˜ Ω√¿€«‘.
glm::mat3 A(0, 1, 4, 0, 1, 2, 1, 1, 1);//ºº∑Œ∑Œ
glm::vec3 bx = glm::vec3(srcPts[0].x, srcPts[1].x, srcPts[2].x);
glm::vec3 by = glm::vec3(srcPts[0].y, srcPts[1].y, srcPts[2].y);//2¬˜ø¯¿Ã¥œ±Ò
glm::vec3 xx = glm::inverse(A) * bx;
glm::vec3 xy = glm::inverse(A) * by;
v0 = glm::vec2(xx.y, xy.y);//t = 0
}
if (k < srcPts.size() - 2)
{
glm::mat3 A(0, 1, 4, 0, 1, 2, 1, 1, 1);//ºº∑Œ∑Œ
glm::vec3 bx = glm::vec3(srcPts[k].x, srcPts[k+1].x, srcPts[k+2].x);
glm::vec3 by = glm::vec3(srcPts[k].y, srcPts[k+1].y, srcPts[k+2].y);//2¬˜ø¯¿Ã¥œ±Ò
glm::vec3 xx = glm::inverse(A) * bx;
glm::vec3 xy = glm::inverse(A) * by;
v1 = glm::vec2(2 * xx.x + xx.y, 2 * xy.x + xy.y); // k+1일 때 이므로 행렬을 보면 t=1
}
else {
glm::mat3 A(4, 1, 0, -2, -1, 0, 1, 1, 1);
glm::vec3 bx = glm::vec3(srcPts[k - 1].x, srcPts[k].x, srcPts[k+1].x);
glm::vec3 by = glm::vec3(srcPts[k - 1].y, srcPts[k].y, srcPts[k+1].y);//2¬˜ø¯¿Ã¥œ±Ò
glm::vec3 xx = glm::inverse(A) * bx;
glm::vec3 xy = glm::inverse(A) * by;
v1 = glm::vec2(xx.y, xy.y); // k+1일 때 이므로 행렬을 보면 t=0
}
p0 = srcPts[k];
p3 = srcPts[k + 1];
p1 = p0 + v0 / 3.f;
p2 = p3 - v1 / 3.f;
ret = (1 - t) * (1 - t) * (1 - t) * p0
+ 3 * (1 - t) * (1 - t) * t * p1
+ 3 * (1 - t) * t * t * p2
+ t * t * t * p3;
} break;
case CATMULL2: {
glm::vec2 p0, p1, p2, p3;
glm::vec2 v0(0), v1(0);
if (k > 0) // Ω√¿€¡° ¿Ã¿¸ø° ¡°¿Ã 毿ª ºˆ ¿÷¿∏¥œ±Ò
v0 = (srcPts[k + 1] - srcPts[k - 1]) / 2.f;
if (k < srcPts.size() - 2)
{
v1 = (srcPts[k + 2] - srcPts[k]) / 2.f;
}
p0 = srcPts[k];
p3 = srcPts[k + 1];
p1 = p0 + v0 / 3.f;
p2 = p3 - v1 / 3.f;
ret = (1 - t) * (1 - t) * (1 - t) * p0
+ 3 * (1 - t) * (1 - t) * t * p1
+ 3 * (1 - t) * t * t * p2
+ t * t * t * p3;
} break;
case BSPLINE: {
if (k<1 || k>srcPts.size() - 3) {
ret = srcPts[k];
}
else {
float B3 = 1.f / 6.f * t * t * t;
float B2 = 1.f / 6.f * (-3 * t * t * t + 3 * t * t + 3 * t + 1);
float B1 = 1.f / 6.f * (3 * t * t * t - 6 * t * t + 4);
float B0 = 1.f / 6.f * (1 - t) * (1 - t) * (1 - t);
ret = B0 * srcPts[k - 1] + B1 * srcPts[k] + B2 * srcPts[k + 1] + B3 * srcPts[k + 2];
}
} break;
case NATURAL: {
size_t N = srcPts.size() - 1;//curve¿« ºˆ
Eigen::MatrixXf A(N+1,N+1);
A.setZero();
A(0, 0) = 2;
A(0, 1) = 1;
for (auto i = 1; i < N; i++) {
A(i, i - 1) = 1;
A(i, i) = 4;
A(i, i + 1) = 1;
}
A(N , N - 1) = 1;
A(N , N ) = 2;
Eigen::VectorXf bx(N+1), by(N+1);
bx[0] = 3 * (srcPts[1].x - srcPts[0].x);
by[0] = 3 * (srcPts[1].y - srcPts[0].y);
for (auto i = 1; i < N; i++) {
bx[i] = 3 * (srcPts[i + 1].x - srcPts[i-1].x);
by[i] = 3 * (srcPts[i + 1].y - srcPts[i-1].y);
}
bx[N] = 3 * (srcPts[N].x - srcPts[N-1].x);
by[N] = 3 * (srcPts[N].y - srcPts[N-1].y);
auto solver = A.fullPivLu();
auto Dx = solver.solve(bx);
auto Dy = solver.solve(by);
glm::vec2 a = srcPts[k];
glm::vec2 b = glm::vec2(Dx[k], Dy[k]);
glm::vec2 c = 3.f * (srcPts[k + 1] - srcPts[k]) - 2.f * glm::vec2(Dx[k], Dy[k]) - glm::vec2(Dx[k + 1], Dy[k + 1]);
glm::vec2 d = 2.f * (srcPts[k] - srcPts[k+1]) + glm::vec2(Dx[k], Dy[k]) + glm::vec2(Dx[k + 1], Dy[k + 1]);
return a + b * t + c * t * t + d * t * t * t;
} break;
case CLOSED: {
size_t N = srcPts.size() - 1;//curve¿« ºˆ
Eigen::MatrixXf A(N + 1, N + 1);
A.setZero();
A(0, 0) = 4;
A(0, 1) = 1;
A(0, N) = 1;
for (auto i = 1; i < N; i++) {
A(i, i - 1) = 1;
A(i, i) = 4;
A(i, i + 1) = 1;
}
A(N, 0) = 1;
A(N, N - 1) = 1;
A(N, N) = 2;
Eigen::VectorXf bx(N + 1), by(N + 1);
bx[0] = 3 * (srcPts[1].x - srcPts[N].x);
by[0] = 3 * (srcPts[1].y - srcPts[N].y);
for (auto i = 1; i < N; i++) {
bx[i] = 3 * (srcPts[i + 1].x - srcPts[i - 1].x);
by[i] = 3 * (srcPts[i + 1].y - srcPts[i - 1].y);
}
bx[N] = 3 * (srcPts[0].x - srcPts[N - 1].x);
by[N] = 3 * (srcPts[0].y - srcPts[N - 1].y);
auto solver = A.fullPivLu();
auto Dx = solver.solve(bx);
auto Dy = solver.solve(by);
glm::vec2 a = srcPts[k];
glm::vec2 b = glm::vec2(Dx[k], Dy[k]);
glm::vec2 c = 3.f * (srcPts[k + 1] - srcPts[k]) - 2.f * glm::vec2(Dx[k], Dy[k]) - glm::vec2(Dx[k + 1], Dy[k + 1]);
glm::vec2 d = 2.f * (srcPts[k] - srcPts[k + 1]) + glm::vec2(Dx[k], Dy[k]) + glm::vec2(Dx[k + 1], Dy[k + 1]);
return a + b * t + c * t * t + d * t * t * t;
}
case LINEAR :
default: {
ret = (srcPts[k+1]-srcPts[k])*t + srcPts[k];
}
}
pointsDirty = false;
return ret;
}
struct CurveWidget : JGL::Widget {
CurveWidget(float x, float y, float w, float h, const std::string& title = "" )
: JGL::Widget(x,y,w,h,title){}
virtual void drawBox(NVGcontext* vg, const glm::rect& r) override {
nvgBeginPath( vg );
nvgRect( vg, r.x, r.y, r.w, r.h );
nvgFillColor( vg, nvgRGBAf(0,0,0,1));
nvgFill( vg );
}
virtual void drawContents(NVGcontext* vg, const glm::rect& r, int align ) override {
if( drawType == DRAW_LINES ) {
nvgBeginPath( vg );
for( auto i=0; i<srcPts.size()-1; i++ ) {
for( float t=0; t<1.0; t+=0.01f ) {
glm::vec2 p = evaluateCurve( i, t );
if( i==0 && t<0.0001 )
nvgMoveTo( vg, p.x, p.y );
else
nvgLineTo( vg, p.x, p.y );
}
}
nvgStrokeColor(vg, nvgRGBAf(0,.3f,1,1));
nvgStrokeWidth(vg, 2);
nvgStroke( vg );
}
else {
nvgBeginPath( vg );
for( auto i=0; i<srcPts.size()-1; i++ ) {
for( float t=0; t<1.0; t+=0.01f ) {
glm::vec2 p = evaluateCurve( i, t );
nvgCircle(vg, p.x, p.y, 1);
}
}
nvgFillColor(vg, nvgRGBAf(0,1,.3f,1));
nvgFill( vg );
}
nvgBeginPath( vg );
for( auto i=0; i<srcPts.size(); i++ )
if( i!= underPt )
nvgCircle( vg, srcPts[i].x, srcPts[i].y, 5 );
nvgFillColor( vg, nvgRGBAf(1,1,0,.8f));
nvgFill( vg );
if( underPt>=0 ) {
nvgBeginPath( vg );
nvgCircle( vg, srcPts[underPt].x, srcPts[underPt].y, 5 );
nvgFillColor( vg, nvgRGBAf(1,.8f,0,.8f));
nvgFill( vg );
}
}
virtual bool handle( int event ) override {
glm::vec2 pt = JGL::_JGL::eventPt();
switch( event ) {
case JGL::EVENT_MOVE : {
int oldPt = underPt;
underPt = -1;
for( auto i=0; i<srcPts.size(); i++ ) {
if( length(pt-srcPts[i])<6 )
underPt = i;
}
if( underPt!= oldPt )
redraw();
}break;
case JGL::EVENT_PUSH : {
if( underPt>=0 )
ptOffset = srcPts[underPt]-pt;
}break;
case JGL::EVENT_DRAG : {
if( underPt>=0 ) {
srcPts[underPt] = pt+ptOffset;
pointsDirty = true;
redraw();
}
}break;
}
return true;
}
int underPt = -1;
glm::vec2 ptOffset = glm::vec2(0);
};
using namespace JGL;
CurveWidget* curveWidget;
void curveTypeCallback(Widget* w, void* ud ) {
curveType = ((Options*)w)->value();
curveWidget->redraw();
}
void drawTypeCallback(Widget* w, void* ud ) {
drawType = ((Options*)w)->value();
curveWidget->redraw();
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
//Eigen::Matrix<float, 3, 3> A; A<<1,3,2, 1,2,3, 5,3,1;
//Eigen::Matrix3f m; //πÃ∏Æ ∏∏µÈæÓ ¡Æ ¿÷¥¬ ∞≈, X¥¬ ≈©±‚∏¶ ∏∏£¥¬ ∞≈
//Eigen::Vector3f b; b << 1, 2, 3;
//auto x = A.fullPivLu().solve(b);
//cout << x(0) << " " << x(1) << x(2) << endl;
Window* window = new Window(640,480,"Curves");
window->alignment(ALIGN_ALL);
Aligner* aligner = new Aligner(0,0,window->w(), window->h());
aligner->type(Aligner::VERTICAL);
aligner->alignment(ALIGN_ALL);
Toolbar* toolbar = new Toolbar(0,0,window->w(), _size_toolbar_height() );
Options* curveType = new Options(0,0,200,_size_button_height() );
curveType->add("Lagrangian");
curveType->add("Linear");
curveType->add("Bezier");
curveType->add("Catmull");
curveType->add("Catmull2");
curveType->add("Bspline");
curveType->add("Natural Spline");
curveType->add("CLOSED Spline");
curveType->value(::curveType);
curveType->callback( curveTypeCallback );
Options* drawType = new Options(0,0,200,_size_button_height() );
drawType->add("Lines");
drawType->add("Dots");
drawType->value(::drawType);
drawType->callback( drawTypeCallback );
toolbar->end();
curveWidget = new CurveWidget(0,0,window->w(), window->h()-toolbar->h());
aligner->resizable( curveWidget );
aligner->end();
for( auto i=0; i<9; i++ ) {
srcPts.push_back(glm::vec2((i*0.1+0.1)*curveWidget->w(),curveWidget->h()/2));
}
window->show();
_JGL::run();
return 0;
}
//
// main3.cpp
// CurveInter
//
// Created by Hyun Joon Shin on 2022/03/08.
//
#define GL_SILENCE_DEPRECATION
#include <GLFW/glfw3.h>
#include "nvg/nanovg.h"
#include "nvg/nanovg_gl.h"
int main(int argc, const char * argv[]) {
glfwInit();
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4 );
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1 );
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true);
GLFWwindow* window = glfwCreateWindow(800, 600, "CurveInter", nullptr, nullptr);
glfwMakeContextCurrent(window);
NVGcontext* vg = NULL;
while( !glfwWindowShouldClose(window) ) {
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
}
return 0;
}
#version 150 core
out vec4 out_Color;
in vec3 worldPos;
in vec3 normal;
in vec2 texCoord;
in vec4 shadow_Position;
uniform vec3 lightPos;
uniform vec3 lightInt;
uniform vec3 ambInt;
uniform vec3 color;
uniform vec3 cameraPos;
uniform float shininess;
uniform vec3 specularColor;
uniform sampler2D colorTexture;
uniform sampler2D bumpTexture;
uniform sampler2D shadowMap;
mat3 getTBN(vec3 N){
vec3 Q1 = dFdx(worldPos), Q2 = dFdy(worldPos);
vec2 st1 = dFdx(texCoord), st2 = dFdy(texCoord);
float D = st1.s*st2.t-st2.s*st1.t;
return mat3(normalize(( Q1*st2.t - Q2*st1.t )*D), normalize((-Q1*st2.s + Q2*st1.s )*D), N);
}
const vec2 poissonDisk[4] = vec2[](
vec2( -0.94201624, -0.39906216 ),
vec2( 0.94558609, -0.76890725 ),
vec2( -0.094184101, -0.92938870 ),
vec2( 0.34495938, 0.29387760 ) );
void main(void)
{
vec3 L = normalize(lightPos - worldPos);
vec3 N = normalize(normal);
mat3 TBN = getTBN( N );
float Bu = texture( bumpTexture, texCoord+vec2(0.0001,0) ).r - texture( bumpTexture, texCoord-vec2(0.0001,0) ).r;
float Bv = texture( bumpTexture, texCoord+vec2(0,0.0001) ).r - texture( bumpTexture, texCoord-vec2(0,0.0001) ).r;
vec3 bumpVec = vec3(-Bu*15., -Bv*15., 1 );
N = normalize( TBN* bumpVec );
vec3 V = normalize(cameraPos - worldPos);
vec3 R = 2*dot(N,L)*N-L;
vec4 albelo = texture( colorTexture , texCoord );
vec3 diffuse = lightInt * max(0, dot(N, L)) * albelo.rgb;
vec3 ambient = ambInt * albelo.rgb;
vec3 specular = lightInt * pow(max(0, dot(R,V)), shininess) * max(0, dot(N, L)) * specularColor;
vec3 shadowCoord = shadow_Position.xyz/shadow_Position.w*0.5+0.5;
float shadowFactor = 1;
float bias = 0.001;
for(int i = 0; i < 4; i++){
if( texture(shadowMap, shadowCoord.xy+poissonDisk[i]/700.).r<shadowCoord.z-bias)
shadowFactor -= 0.25;
}
out_Color = vec4(pow((diffuse + specular)*shadowFactor + ambient, vec3(1/2.2)), 1.0);
}
#version 410 core
layout(location=0) in vec3 in_Position;
layout(location=1) in vec3 in_Normal;
layout(location=2) in vec2 in_TexCoord;
uniform mat4 modelMat;
uniform mat4 viewMat;
uniform mat4 projMat;
uniform mat4 shadowMVP;
out vec3 worldPos;
out vec3 normal;
out vec2 texCoord;
out vec4 shadow_Position;
void main(void)
{
worldPos = (modelMat*vec4(in_Position, 1)).xyz;
normal = (modelMat*vec4(in_Normal, 0)).xyz;
texCoord = in_TexCoord;
gl_Position= projMat*viewMat*modelMat*vec4(in_Position, 1.0);
shadow_Position = shadowMVP*vec4(in_Position, 1.0);
}
#version 410 core
out vec4 out_Color;
void main(void)
{
out_Color = vec4(vec3(gl_FragCoord.z), 1);
}
#version 410 core
layout(location=0) in vec3 in_Position;
uniform mat4 shadowMVP;
void main(void) {
gl_Position= shadowMVP * vec4(in_Position, 1);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment