3D 모델을 만드는 방식은 여러가지가 있지만,
tinylender는 일러스트레이터처럼 먼저 펜툴로 2D 도형을 그린 다음, 그걸 3D화 시킬 생각이다.
그래서 우선 2d 메시를 만들 수 있는 펜툴을 만들었다.
pen
class Pen: public IPressedDown,public IMoved,public IState{
public:
Pen();
void DrawMesh();
void OnPointerDown(float xpos, float ypos,float xdelta,float ydelta) override;
void OnMove(float xpos, float ypos,float xdelta,float ydelta) override;
void Handle() override;
void HandleOut() override;
private:
std::vector<Vertex> mVertices;
std::vector<unsigned int> mIndice;
unsigned int mVBO;
unsigned int mVAO;
unsigned int mEBO;
float mLineVertices[9] = {
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f};
unsigned int mLineVBO;
unsigned int mLineVAO;
bool bDraw=false;
bool bFirst=true;
glm::vec3 screenToLocal(glm::vec2 screen);
};
void Pen::OnPointerDown(float xpos, float ypos,float xdelta,float ydelta){
if(!bDraw)
return;
glm::vec3 point = screenToLocal(glm::vec2(xpos,ypos));
Vertex vert = {point,glm::vec3(1.0f),glm::vec2(1.0f),glm::vec3(1.0f)};
if(glm::length(point-mVertices[0].Position) <= 0.1f &&mVertices.size()>3){
//mesh로 만들어서 collection에 추가
std::vector<std::vector<unsigned int>> faces;
std::vector<unsigned int> f;
faces.push_back(f);
for(int i=0;i<mVertices.size();i++){
faces[0].push_back(i);
faces[0].push_back(i);
faces[0].push_back(i);
}
Mesh* mesh= new Mesh(mVertices,mIndice,std::vector<Texture>(0),faces,"Shader/vertexShader.glsl","Shader/fragmentShader.glsl");
Collection::GetInstance()->SetMesh(mesh);
mVertices.clear();
mVertices.push_back({glm::vec3(0.0f),glm::vec3(0.0f),glm::vec2(0.0f),glm::vec3(0.0f)});
mIndice.clear();
bFirst=true;
return;
}
else{
mLineVertices[0] = point.x;
mLineVertices[1] = point.y;
mLineVertices[2] = point.z;
if(bFirst){
mVertices[0] = vert;
mLineVertices[6] = vert.Position.x;
mLineVertices[7] = vert.Position.y;
mLineVertices[8] = vert.Position.z;
glBindBuffer(GL_ARRAY_BUFFER,mLineVBO);
glBufferSubData(GL_ARRAY_BUFFER,6*sizeof(float),3*sizeof(float),&mLineVertices[6]);
}
else{
if(mVertices.size()>=3){
Vertex vert2 = mVertices[mVertices.size()-1];
mVertices.push_back(mVertices[0]);
mVertices.push_back(vert2);
mVertices.push_back(vert);
}
else{
mVertices.push_back(vert);
}
}
glBindVertexArray(mVAO);
glBindBuffer(GL_ARRAY_BUFFER,mVBO);
glBufferData(GL_ARRAY_BUFFER,mVertices.size()*sizeof(Vertex),&mVertices[0],GL_DYNAMIC_DRAW);
//glBindVertexArray(mLineVAO);
glBindBuffer(GL_ARRAY_BUFFER,mLineVBO);
glBufferSubData(GL_ARRAY_BUFFER,0,3*sizeof(float),&mLineVertices);
}
bFirst=false;
}
OnPointerDown은 마우스 클릭을 할 때 한번 호출된다.
일단 현재 클릭한 위치를 ndc로 변환하고,
mVertices에 해당 값을 넣고 VAO, VBO를 업데이트 해준다.
만약 클릭한 위치가 첫 포인트와 거리가 0.1 미만이고,
mVertices에 들어있는 버텍스가 3개 이상이면
메시로 만들어서 콜렉션에 추가한다.
void Pen::OnMove(float xpos, float ypos,float xdelta,float ydelta){
if(!bDraw)
return;
glm::vec3 point = screenToLocal(glm::vec2(xpos,ypos));
mLineVertices[3] = point.x * PEN_SPEED;
mLineVertices[4] = point.y * PEN_SPEED;
mLineVertices[5] = point.z * PEN_SPEED;
}
추가로 IMoved라는 인터페이스를 만들어서
마우스가 움직일 때마다 호출되도록 만들었다.
Pen에서의 OnMove의 역할은
어떤 도형이 만들어질지 미리 보여주는 역할이다.
이런 미리보기는 라인으로 보여주게 했다.
이렇게 색깔바꾸기도 가능하다 ^_^
일단은 가장 기본적인 기능만 만들었고
곡선이나 원, 사각형 등의 기능은 앞으로 추가할 예정이다.
'컴퓨터 그래픽스 > OpenGL' 카테고리의 다른 글
#8 Tinylender 개발일지 : 레이어 개발(1) (0) | 2024.07.25 |
---|---|
#7 tinylender 개발일지 : extrude 기능 개발 (5) | 2024.05.31 |
#5 tinylender 개발일지 : 상태 머신 적용 (0) | 2024.05.12 |
#4 gulender 개발일지 : mesh, model 그리고 assimp 세팅 (0) | 2024.05.12 |
#3 gulender 개발일지 : rpath 설정 (0) | 2024.05.08 |