2017년 11월 28일 화요일

js 유효성? 뭔지모를 문제점과 해결책




예전에 비트할때에도 웹 jsp의 이상한 구조로 인해 고통받았었는데,
(페이지 로딩 전과 후의 문제로 인해 함수의 작동 유무 따위의)

다시 그 고통속에서 해엄치고 있습니다.

우선, js 뿐만 아니라 다른곳에서도 비슷한 일이 있던걸로 아는데, 다시한번 나타난 문제로,
var text = '<span id="testspan" onclick="Foo()"'>hello</>';
의 경우입니다.
innerHTML 혹은 append 따위를 이용하기 위해 만든 변수인데, 작동상에 문제가 없습니다.

하지만, Foo함수 안에 파라메터를 입력할때에 문제가 발생했습니다.

ajax통신,
success(value):
  var text = '<span id="testspan" onclick="Foo( ? )"'>hello</>';
  document.getElementByid('testDiv').innerHTML=text;

function Foo(value){
 console.log(value);
}
에서 ? 의 케이스 입니다.
처음 생각했을 때에는
var text = '<span id="testspan" onclick="Foo('+value+')"'>hello</>';
로 생각을 했었으며, 결과적으로
value function은 선언되지 않았따는 오류를 띄웠습니다.

 var text = '<span id="testspan" onclick="Foo("'+value+'")"'>hello</>';
를 시도했을떄는 위치를 알 수 없는 신텍스 에러가 났습니다.

문제점은 double quota 였습니다. onclick 시 이미 쌍따움표를 이용해 들어갔는데, 내부에서 다시 쌍따움표로 막혔기 때문에, 이후 모든 syntax들이 꼬이게 되었습니다.

Foo함수 내부의 parameter에서 double quota 를 읽지 않게 하면 됩니다.

이를 예전에 유효성 관련 과제로 처리하는게 있었는데.. 아무튼
js의 케이스에서  " 를 무시시키는 것은 간단히 \ 를 쓰는것으로 해결되었습니다.
 var text = '<span id="testspan" onclick="Foo(\"'+value+'\")"'>hello</>';
보고 속이 울렁거리는걸 꾹 참고 정독해 보면, double quota 가 필요하나, 읽지 않아야 할 부분 앞에는 \ 가 붙어있음을 볼 수 있습니다.


2017년 11월 21일 화요일

c 룰렛게임?

죄수 n ( 1이상 1000이하) 명, 회전 횟수 k ( 1이상 n 이하)가 있으며,
시작지점 0번째 실린더 위치를 p, k만큼 실린더가 돕니다.
선택된 실린더 p의 죄수는 처형당하며, 사라진 죄수의 다음 위치에 p가 설정됩니다.

이 작업이 반복되면서, 마지막 남은 죄수가 몇번째 인가, 그리고 처형된 순서대로 로그에 남기는 문제입니다.

이주짜리 과제...2주나?
단일 소스 코드로, 환형 리스트,클래스없이 구현하는게 제약조건이었습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include<stdio.h>
#include<stdlib.h>
typedef struct prisoner {
    int prisonerNum;
    struct prisoner* next;
}PRISONER;
typedef struct killLog {
    int *log;
}KILLLOG;
PRISONER* init(int size){ //리스트 선언,초기화
    int num = 1;
    PRISONER* neww = (PRISONER*)malloc(sizeof(PRISONER));
    PRISONER* cur,* tmp = NULL;
    cur = neww;
    cur->prisonerNum = num;
    if (size == 1) {
        cur->next = neww;
        return neww;
    } //죄수가 한명일때, 쓸모없지만, 문제에서 제시한 범위는 1명 이상이다.
    while (num != size) {
        tmp= (PRISONER*)malloc(sizeof(PRISONER));
        cur->next = tmp;
        cur = tmp;
        cur->prisonerNum = ++num;
    }
    cur->next = neww;
    cur->prisonerNum = num;
    return neww;
}
int roll(/*cbv*/PRISONER **killPoints, int size,KILLLOG *killLog,int *killCount) {
    PRISONER* tmp = *killPoints;
    int count = size;
    if ((*killPoints)->next == *killPoints)
        return 1;// 죽일 죄수가 하나뿐일떄
    
    while (count != 1) {
        *killPoints = (*killPoints)->next;
        count--;
    } // 죽일 죄수를 정한다.
    
    while (tmp->next != *killPoints)
        tmp = tmp->next;//죽일 죄수의 prev로 간다.
    
    tmp->next = (*killPoints)->next; // 죽일 죄수의 링크드 리스트를 연결을 해제
    tmp = *killPoints; //죽일 죄수는 tmp포인터가 이제 지목한다.
    *killPoints = tmp->next; // 다음 죽일 죄수를 위해 포인터가 다음칸으로 이동한다.
    //printf("current killpoint is %d \n", (*killPoints)->prisonerNum); 
    tmp->next = NULL; //죽일 죄수의 노드를 말끔히 지운다.
    killLog->log[(*killCount)++]=tmp->prisonerNum;//죽일 죄수의 번호를 로그에 입력
    //printf("kill number is : %d \n", tmp->prisonerNum);
    free(tmp);//죽인다.
    return 0;
    
    //죄수가 1명이 되면 return statement는 true가 된다, 그렇지 않으면 false가 되어 함수가 반복된다.
}
int main() {
    int n, k,result=0,killCount=0;
    PRISONER *killMark;
    KILLLOG *killLog;
    
    scanf("%d", &n);
    //죄수의 총 숫자
    scanf("%d", &k);
    //순번 카운트 
    if (!(n > 0 && n < 1001))
        return 0; //예외처리
    if (!(k > 0 && k < n))
        return 0; //예외처리
    killLog = (KILLLOG*)malloc(sizeof(KILLLOG));
    killLog->log = (int*)malloc(sizeof(int)*n);
    //문제 의도대로 살해 순번을 나타내기 위해 동적 배열 생성, 짜놓고도 무식한 방법이네요.
    killMark = init(n);
    //싱글 환형 링크드 리스트로 세팅 완료
    
    while(result!=1)
        result = roll(&killMark, k,killLog,&killCount);
    //하나 남을때까지 죽이는 함수.
    printf("survived prisoner's number is %d \nkilllog : ", killMark->prisonerNum);
    for (int i = 0; i < killCount; i++){
        printf("%d ", killLog->log[i]);
    }
    
    //킬 로그 출력
    free(killMark);
    free(killLog->log);
    free(killLog);
    //마지막 동적 생성된 구조체를 지운다.
    
}
/*
    Project : Assignment for DataStruct
    Creator : Changwon J.
    Date : Nov 06, 2017
    note :  n ist prisoner number, k ist number for counting,
            called "요셉문제" 
*/

2017년 11월 17일 금요일

Node.js/Javascripts 소숫점 자를때 생기는 문제점..

가지고 있는 Double 혹은 Float 타입의 값의 소숫점을 자를 필요가 있었는데,
우선 결론적으로는 간단한 함수를 쓰면 된다.

var value = 3.14;
console.log(value.toFixed(1));
// 결과는 3.1 이 나오게 된다.

toFixed는 반올림 을 해주며, 이미 여러곳에서 쉽게 검색을 할 수 있는데, 추가적인 작업중에 꽃피는 애로사항이 나를 맞이하였다,

javascripts를 내가 싫어하는 이유중 하나가 바로 데이터타입을 원하는데로 선언이 안되던건데, 아니나 다를까 여기서 발목이 잡혔다.

toFixed 함수의 리턴갑은 String 타입이다.

이를 확인하기 위해서 간단히
console.log(typeof value);
//결과는 string

를 이용했었다.

결론적으로 String이어서 또 캐스팅을 해야하는 짜증나는 문제가 생겼는데,이미 정의된 함수를 뜯어고치는것도 내 수준에서는 정신나간짓 인거같고, 또 캐스팅을 하자니 뭔짓인가 싶어서 조금 더 검색을 해 봤는데 결과는 너무나 간단하게 해결이 가능했다.

console.log(value.toFixed(1)/1);
1을 나눠주게 해버리니깐 number 타입으로 다시 바꾸더라.

익숙해지기 힘드네..

2017년 11월 16일 목요일

ejs, script 문에서 서버 전송 값 다루기..

이놈의 ejs는 할때마다 까먹고 해괴한데, 두번째로 변수값에 대한 글을 남기게 되었습니다.

ejs파일 속의 <script>안에서, 서버에서 전송한 값은 어떻게 받을까 고민하며,

<script>
 var val = <%- test %>
</script>
로 해봤는데 그냥 뻗어버리는 사태가 계속해서 발생..

짜증 이빠이 나서 검색해보니 의외로 간단 -_-;;
서버사이드에서 넘길때 변수타입이 이상해서 못받고 뻗어버리는것.
그러니깐 어뜨캐 하냐면
var val = <%- JSON.Stringify(test) %>

js는 ㄹㅇ 난 못하는듯 합니당. 너무 답답하고 미칠거같아서 눈물이 다 나려하더라

2017년 11월 7일 화요일

11월 7일 ejs 태그 문제

과제폭탄으로 여태까지 업데이트가 없어쓰..

오늘까지 된것.
ejs공부
express 기초 다시 공부
mysql 통신성공
sql query문을 통해 데이터 판독 성공

다음 해야할 일들
passport와 session을 이용해 세션 설정.
bcrypt를 이용한 비밀번호 암호화
1차 코드 보강
뷰 연동
2차 서버 통신 준비




ejs 에서 조건문을 쓸때 유의해야하는 사항이 하나 있는데, <% %>를 언제 끊어야 하나 였습니다.

jsp에서는 이런식일때는 문제가 없었는데,

<% if(condition){
%><script>blah </><%
}else{
%> <script> blah2</> <%
}%>

지저분하기야 jsp를 만질때부터 느끼고는 있었으나 사용에는 문제가 없었으므로, 이의를 제기하지 않고 썻었습니다.

헌데 ejs에서는 문법 오류를 뿜어대는데, 도저히syntex오류를 찾을수 없어 조금 더 검색을 하다가, 결론이 나왔습니다.
https://stackoverflow.com/questions/8216918/can-i-use-conditional-statements-with-ejs-templates-in-jmvc

<!-- if문 -->
<% if(condition) {%>
<script>blah</>
<% }else{ %>
<script>blah2</>
<%}%>

<!-- while문-->
<% while(condition) { %>
<script>blah3 </>
<% variable++
} %>

<!-- switch문 -->
<%switch(condition){
 case 1 : %>
<script> blah4</>
<% break;
 case 2 : %>
<script> blah5</>
<% break;
default : break;
} %>

차이가 뭐냐 싶었는데, 속된말로 ㅈ대로 꺽쇠를 열었다 닫았다를 못합니다.
jsp에서는 쓰는놈 마음대로 어느정도 꼬을 수 있다고 보는데, ejs에서는 규칙을 정해놨네요.
 태그를 닫는순간 그 뒤에 다시 열기전에 태그문이 아닌 다른것이 들어가야 하더군요.
정확하게 설명글을 아직 보지는 못했지만, 잃어버린 내 4시간을 위해 써둡니당.



2017년 10월 30일 월요일

10월 30일

서버 설계도 작업을 시작했습니다.
아직 초보이며, 서버에 대한 기초지식이 부족한 관계로, 처음에는 가볍게
3계층 구조를 시도해 볼 생각입니다.
client - was - dbms 로 1차 구현 입니다.

express 를 이클립스에 올리기를 어제 실패했습니다.
보통 인터넷에 알려주는 방법은 npm을 사용하는데, 아직은 방법을 이해하지 못했습니다.
조금 더 알아보았고, 결국은 eclipse용 express를 설치하는데 성공했습니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//express 사용방법. package.json이 선언되어 있어야 한다.
var express = require('express');
var app = express();
var route = require('./router/main.js')(app); //라우트 폴더의 js파일을 인식시키게 하는 코드,(app)로 인자값 전달.
 
app.set('views',__dirname+'/views');
app.set('view engine','ejs');
app.engine('html',require('ejs').renderFile);
app.use(express.static('public')); //css파일,이미지,동영상등 변하지 않는 리소스들을 보관하는 폴더엔 public 내부를 인식.
 
var server = app.listen(8081, function(){
    console.log('Express erver ist on at 8081');
});
 
//app.get('/',function(request,response){
//    response.send('Hello World');
//})
//라우터 사용방법. 라우터란 jsp의 mvc패턴의 controller와 비슷한 기능을 제공하는 기능이다.
//올바른 코드를 위해서는, 라우터 코드를 따로 폴더에 저장한다.
 



express 에서는기존의 Node의 서버 실행과는 조금 다른방식으로, 변수에 express를 불러와서,

그 변수를 이용하여 서버를 세팅하고, 구동합니다. 위의 코드에서 app 라는 variable이 그 역활을 담당합니다.
서버의 오픈은 11번 라인입니다.

이후 서버로부터 사용자의 요청을 받기 위해서는, 라우터가 필요합니다.
라우터는 JSP에서 controller를 부분적으로 담당하는 기능입니다.
클라이언트로부터 들어온 요청대로 경로를 뿌려주는 기능입니다.

아래 15번 라인이 라우터의 예시입니다. 메인 소스에 지저분하게 얹히는것이 싫기 때문에, 코드를 따로 뺍니다.

./router/main.js 에 라우터를 설정합니다.
1
2
3
4
5
6
7
8
9
module.exports = function(app)
{
    app.get('/',function(request,response){
        response.render('index.html');
    });
    app.get('/about',function(request,response){
        response.render('about.html');
    });
}

이로써 따로 빼낸 라우터가 준비되었습니다. 처음의 4번 라인에서, 방금 만든 코드를 인클루드 합니다.

이제 html들을 준비합니다.
만든 html파일들을 따로 보관하기 위해,
./views/ 안에 html들을 저장했습니다.

라우터 코드에 html들의 이름이 적혀져 있습니다. 하지만 정확한 html의 실행 경로는 설정 되어 있지 않기 때문에, 제일 상단의 6번 라인을 선언합니다. 이로써views 는 ./views/ 로 설정이 된다 합니다.


css, 정적인 이미지나, 동영상 등은 정적이므로, node에서 여러번 생성 할 필요가 없습니다.
그런 이유에서 상기의 리소스들을 static화를 시킵니다.
css 파일을
./public/css/style.css 위치에 지정했습니다.
 메인클래스에서 static선언과, 위치를 알려주는 코드는 9번 라인 입니다.

이제 html에서는
1
<link rel="stylesheet" type="text/css" href="css/style.css">

를 헤더에 선언하면, 적용이 된 css를 볼 수 있게 됩니다.






이정도 까지..

보고 배운, 출처 블로그 : https://velopert.com/294

project pid 시작!

새 프로잭트를 준비하며, 일지를 다시 작성합니다.
앞으로 최대한 일지를 작성할 것이며, 이전처럼 겪은내용, 애로사항, 해결법, 등을 기술 할 것 입니다.

새 프로잭트인 pid에서 제가 맡은 역활은 서버 생성 입니다.

Node.Js 를 이용하여 기본 서버 설계, 나아가 리눅스 기초를 만져 볼 생각입니다.

2017년 9월 25일 월요일

Hanoi Tower with discription

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include<iostream>
using namespace std;
#define TOWERSIZE 5
class blocks { //하노이탑의 각 블록의 클래스화 입니다.
private:
    int blockSize; //해당 블록이 몇칸짜리인지 이 변수를 통해 알아냅니다.
public:
    void setBlockSize(int num) 
    {
        blockSize = num;
    }
    int getBlockSize() 
    {
        return blockSize;
    }
};
class lists { //from,tmp,to 탑을 클래스화 시켰습니다.
private:
    int top = -1; //stack을 위해 top변수를 만들었습니다.
    blocks blockslist[TOWERSIZE];//각 탑의 층수 입니다.
public:
    int getTop() 
    {
        return top;
    }
    void pushBlock(blocks in) 
    {
        blockslist[++top] = in;
    }
    blocks popBlock() 
    {
        return blockslist[top--];
    }
    int peekBlock() 
    {
        return (blockslist[top]).getBlockSize();
    }
    int peekSelectBlock(int selectedSize) //특정 위치를 peek하기위한 함수
    {
        return (blockslist[selectedSize]).getBlockSize();
    }
};
void printTower(lists *forPrint) {//탑 출력 함수, 세 탑을 인자값으로 받음
    int i = TOWERSIZE-1; //타워의 꼭대기부터 시작합니다. 
    while (i > -1) //1층까지 반복
    {
        cout << " ";
        if (forPrint[0].getTop() >= i) //탑의 꼭대기가, 현제층보다 같거나 클때 
        {
            int j = 0;
            for (; j < forPrint[0].peekSelectBlock(i); j++) //블럭의 사이즈만큼 *을 찍습니다.
                cout << "*";
            if (j != 5) //5칸을 다 못찍었다면
            {
                while (j != 5)  //남은칸은 whitespace
                {
                    cout << " ";
                    j++;
                }
            }
        }
        else //현제층이, 탑의 꼭대기보다 높으면
        {
            cout << "     ";//해당 층에는 아무 블럭도 없습니다.
        }
        cout << " ";
        if (forPrint[1].getTop() >= i)  // 두번째 탑
        {
            int j = 0;
            for (; j < forPrint[1].peekSelectBlock(i); j++) 
                cout << "*";
            if (j != 5) 
            {
                while (j != 5) 
                {
                    cout << " ";
                    j++;
                }
            }
        }
        else 
        {
            cout << "     ";
        }
        cout << " ";
        if (forPrint[2].getTop() >= i) //세번째 탑
        {
            int j = 0;
            for (; j < forPrint[2].peekSelectBlock(i); j++)
                cout << "*";
            if (j != 5) 
            {
                while (j != 5) 
                {
                    cout << " ";
                    j++;
                }
            }
        }
        else 
        {    
            cout << "     ";    
        }
        cout << endl;
        i -= 1; //다음층의 계산을 시작합니다.
    }
    cout << " ----- ----- -----" << endl; // 바닥.
}
void calcHanoi(int num, lists *from, lists *tmp, lists *to, lists *forprint)
{//하노이 계산 함수
    if (num == 1)
    {
        to->pushBlock(from->popBlock());
        printTower(forprint);
        return;//기존과는 달리, 블럭 클래스들을 stack을 이용해 list클래스에 붙혀줍니다.
    }        //118번줄은 이 작업을 담당합니다. 이동후 타워를 출력합니다.
    calcHanoi(num - 1, from, to, tmp, forprint);
    calcHanoi(1, from, tmp, to, forprint);
    calcHanoi(num - 1, tmp, from, to, forprint);
}
void main() {
    int num = TOWERSIZE;
    blocks block[TOWERSIZE]; //블럭 클래스를 생성합니다.
    lists list[3];            //타워 클래스를 생성합니다.
    for (int i = 0; i < num; i++) {
        block[i].setBlockSize(num - i);//블럭을 순서대로 초기화 합니다.
        list[0].pushBlock(block[i]);//from 탑에 순서대로 생성한 블럭을 쌓습니다.
    }
    //여기까지 초기화 작업
    calcHanoi(num, &list[0], &list[1], &list[2], &*list);
    
   cout<<"DONE"<<endl;
}
/*
    Sep,18 2017 19:21
    Creater        : Changwon J.
    Title        : HanoiTower 
    Version        : Ver 1.0
    Discription    : print HanoiTower as ordered, comment added
*/

간만에 코드짜니깐 겁나 더러운것.
혹시 과제 빼낄친구들이 있을수도 있으니,
9월 25일 이후에 공개할것.

2017년 9월 24일 일요일

MsSQL2012 설치

교수가 설치법을 몰라서 당황..

당연하게도 MS사의 sql은 비쌈. 넘나비싼것.

그래서 평가판이 있다능.

https://www.microsoft.com/ko-kr/download/details.aspx?id=29062


...

걍 받고설치하면 되는데? 왜 그렇게 당황했는지 아무도 몰라..

2017년 9월 19일 화요일

c+ 다수의 소스나 헤더 적용법과 에러

오늘 배운 수업중 하낙가, 다수의 소스와 헤더파일의 구동법이었는데, 일전에 언리얼 코드를 뜯어본 기억이 새록새록 돋아나 흥미롭게 들었습니다.

겪어 본 이후로 더욱 더 실감하지만, 하나의 프로잭트에 여러명이 붙는순, 학생들이 배우는 방식의 코드작업은 지옥을 초래하게 됩니다.

(하나의 소스파일로 두세명이 작업하는것도 무리인데, 회사의 경우는 두세명이 아닐태니깐!)

그러한 이유로 우리는 여러개의 소스 파일과 헤더들을 이용하여 쉽게 지옥을 물리칠 수 있습니다.

우선적으로 우리가 컴파일을 시작하면, 프로잭트의 모든 Source 파일들을 읽기 시작하죠.

그 중 #include 문이 있다면,include가 가리키는 라이브러리, 혹은 헤더파일을 방문하여 읽게 됩니다.

미리 define된 라이브러리 함수들은 꺽쇠인 < > 로 include를 합니다.

하지만 우리가 만드는 사용자정의 Header는, 보통 하나의 프로젝트 내에 있기 때문에, 단순히 #include "Header이름.h" 를 사용하면 됩니다.

이렇게 선언된 글을 컴파일러가 읽게되면, 만든 header로 방문하게 되어, 선언문들을 읽은뒤, 마저 Source들을 읽게 됩니다.

저와 같은 기초반을 들었던 사람들이라면 흔히 봤을 광경입니다.


기초과정이기도 하고, 중점 교과과목은 자바였기 때문에, 깊게 파고들지 않아서 하나의 예제당 하나의 프로젝트를 만드는게 아닌, 이렇게 소스파일만 새로 만들어서, 이전 예제는 컴파일 재외를 했었습니다.

저는 개인적으로 하면서, 왜 제외해야하나몹시 궁금했었고, 고급과정을 하는동안 까마득히 잊고있었습니다.

정답은 프로젝트를 컴파일하면, 내부의 모든 소스파일들을 컴파일러가 읽어버리기 때문이었습니다.

유일하게 하나이어야만 하는 main 함수, 하나의 프로젝트에 여러번 나오게 될 경우 당연히 문제가 발생했기 때문에, 우리는 귀찮게도 이전 예제 소스파일들을 하나하나 컴파일 예외  시켰습니다.

그럼 이제 여러개의 소스파일을 컴파일 하는방법이 감이 오네요! 여태까지 안하게 막고있었으니, 그 작업만 한하면 되는거였네 ㅎㅎ;

그럼 간단한 stack 을 만들어 봅니다.
목표는
1. 클래스로 두개의 스택구조를 만들것,
2. int타입을 100개 stack 가능하며,
3. 메인 소스파일과, 함수 소스파일은 별개로 만들 것 입니다.

클래스 선언은 Header에서 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Stack
{
private : 
    int arr[100];
    int top;
public  :
    Stack() {
        for (int i = 0; i < 100; i++) 
            arr[i] = 0;
        top = -1;
    }
    void push(int value);
    int pop();
};

클래스에서는 push와 pop함수를 내장하고 있습니다. 두개의 동일한 stack구조를 만들것 이기때문에, 하나의 클래스에 모조리 넣었습니다.
하지만, 함수를 선언만 가능하며, 함수의 내용은 Header에서 함수의 내용을 적지는 않습니다.


 

헤더의 사용 이유는 이러합니다.
SourceA.cpp
----------
void FuncA(){
 FuncB();
}
-----------

SourceB.cpp
-----------
void FuncB(){
}
-----------
의 케이스에서, 우리 기대와는 달리 SourceA에 FuncB() 는 인식하지 않습니다.
이를 해결하기 위해서는

SourceA.cpp
----------
void FuncB();
...

void FuncA(){
 FuncB();
}
-----------
요로코럼 Forward declaration을 해야만 합니다.

이 작업이 수많은 소스파일들도 다 해주어야만 하면, 끔찍하고 지루한 반복작업이 되기떄문에, 이를 해결하기 위해 나온것이 헤더인 것 입니다.

선언을 돕는거죠.



2017년 9월 7일 목요일

Callback Function과 Iterator

재귀함수와 이터레이터는 일찍이 알았습니다만, 재귀함수를 자주 이용하지는 않았습니다.

처음으로 재귀함수를 응용했던것이 C 자료구조 수업에서 quick sort를 만들때 였으며,
그때 정말 눈 돌아갈 정도로 복잡했었기 때문에 사용을 꺼려하고 있었습니다.

재귀함수와 이터레이터는 같은 기능을 제공합니다.특정 기능을 반복하는 행위이지요.

하지만 두 기능은 상황에 따라 작업속도의 차이가 생기게 됩니다.
간단한 예를 들어 피보나치 수열 계산일때 :

반복문을 이용했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int itrway(int var)
{
    if(var<3) return 1;
    else
    {
        int cur=1,prev=1,tmp=0;
        for(int i=2;i<var;i++)
        {
            tmp=cur;
            cur+=prev;
            prev=tmp;
        }
        return cur;
    }
}
재귀함수를 이용했습니다.
1
2
3
4
5
6
7
int functionway(int var){
    
    if(var<=2) return 1;
    else return functionway(var-2)+functionway(var-1);
    
}














같은 기능을 수행하지만, 동작시간은 상이합니다.

number input : 45

1 . function call
 result :1134903170
 exec time :19.725

2 . Iterator call
 result: 1134903170
 exec time :4.724

반복문의 경우에는, 단순하게 수열을 순서대로 더했습니다. 아마..44번 계산이 전부이죠.

반면, 재귀함수의 경우에는 하나의 함수에서 2번의 함수 호출을 합니다.인자값이 1과 2가 아닌이상 또 2번 호출을 하게되고요. 불필요하게 같은 수를호출하게 될 것 입니다.

고작 45라는 숫자이기에 커다란 차이는 없지만, 숫자가 커질수록 작업 횟수와 시간은 기하급수적으로 늘어날 것 입니다.

그렇다고 재귀함수가 항상 안좋은 것은 아닙니다.
대표적인 예로, 검색 알고리즘에서는,
이터레이터 방식의 검색인 버블소트는, 굉장히 쉽게 설계가 되지만, 제가 사용했던 퀵 소트를 비교한다면, 엄청난 수준의 시간 차이가 발생했습니다.

예제를 찍어내는건 담에 하고 ㅠ

이러한 이유로, 수월하고 가벼운 프로그램을 짜기 위해서는, 우리는 최대한 경량화 작업, 그러니깐 좋은 알고리즘을 짜는 방식을 만들기 위해 반복문과 재귀함수중 어느것이 상황에 따라 더 유리한지 찾아야 할 것 입니다.


9월 08일

오랫동안 업데이트가 되지 못했습니다.
작업의 마무리를 위해 눈만뜨면 컴퓨터위로 기어올라가는 일상을 보냈기 때문이라고 변명합니다..

마무리는 거의 끝났습니다.
그 무엇보다 모델링의 부재로 인해 결국 계획됬던 많은 기능들이 사라졌습니다.
만족스럽지 못하지만, 현실적으로 봐야죠.

아직까지 모델링 부분은 끝마치지 못했습니다.
남은 일주일간 건물 모델링에 투자가 될 것 입니다.

그나마 만족스러운 결과물을 얻길 바라며..

2017년 8월 7일 월요일

8월 04일

8월 04일

주간보고

주간 있었던 일을 빠르게 보고하겠습니다.
1. 메뉴작업 착수
2. DB관리 착수
3. 매장 템플릿 추가 작업 착수

로 크게 나눌 수 있겠습니다.



1. 메뉴작업 착수

우선은 크게 네가지 매뉴를 준비했습니다.
홈 메뉴
공지사항 메뉴
캐릭터 커스터마이징 메뉴
옷입히기 메뉴

입니다.
작업은 끝이났습니다. 최대한 추가작업의 편의성을 위해 캐릭터 커스터마이징과 옷입히기 메뉴는 함수화를 구현하는데 중점을 두었습니다만, 아직까지 옷입히기 메뉴에서는 소트나 검색의 기능이 없는 상태입니다.

이 작업은 여유가 생기면 추가 할 작업으로 남겨두었습니다.

그 전에 우선 해야할 일이 있습니다.



2. DB관리

가 다음 작업 사항입니다.

기본적으로 캐릭터 DB에는
캐릭터의 종류, 그 캐릭터에 맞는 각 부위별 신체사이즈 가 있으며,
추후 최저, 최고치 신체사이즈가 입력되어 제한을 걸 수 있도록 해야할 것 입니다.

이부분에서 잠깐 멈춘 이유는, 남아있는 3주동안, 여성 캐릭터의 UV를 올바르게 펴지 못하는 문제에 봉착했으며, 사이즈 증감에 따른 올바른 값을 구하는 방법이 아직 정해지지 못했기 때문입니다.

작업의 진행을 위해 저희팀은, 과감히 4개의 캐릭터를 포기하고, 하나의 캐릭터로 우선작업을 결정했습니다.
디자이너가 가장 가슴아파 하고있습니다만, 그 역시 사태의 심각성을 파악하고 있기 때문에, 시간이 나면 반드시 여성 캐릭터를 추가해 줘야한다 하며 이해해 주었습니다.

그래서 현제 캐릭터 커스터마이징 상태는 170 키의 캐릭터 하나만이 존재 할 뿐입니다.

두번째로 옷 관련 DB입니다.
이곳에서는 테이블이 재법 많고, 생각할 거리도 많아집니다.

우선은 테스트를 위해 순서/이름/이미지경로/메쉬경로/타입/디테일정보 정도로 가볍게 만들었으며, 그 값들을 올바르게 나타내는것에는 무리가 없습니다.

여기서 sort 나 search 등을 이용하기 위해서는 테이블의 확장이 필요합니다.

이는 다음주 부터 이야기를 해 나가야 할 사항입니다.

팀장과의 최대한 빠른 타협을 이끌어내야, 메뉴의 완성과 예외처리를 할 수 있을것 입니다.


3. 매장 템플릿 추가

이부분 또한 VR에 없어서는 안될 작업임은 분명합니다.

개인적인 생각은 다르지만, 전체적인 팀원의 의견은 시각적으로 보여줄것이 많아야 흥미를 유도할 수 있는 요소이다고 주장이 유지되고 있기때문에, 탬플릿을 귀하고 매장을 꾸미는 일은 멈출 수 없습니다.

이부분은 디자이너와 팀장의 콜라보만이 이루어 지고 있기때문에, 제가 자세한 정보는 구하기 힘든 부분입니다.

간간히 마야나 맥스의 작업중 문제가 생기면 기술적인 지원을 같이 하고는 있습니다. 결론적으로 제가 보기에 커다란 문제는 없다고 판단되고 있습니다.


4.다음주를 향해서..

이제 주간 보고를 마무리 지으며, 남아있는 3주에 대한 계획을 시작합니다.
발표준비도 있어야 하기 때문에, 실질적으로 주어진 시간은 2주 이하입니다.

현실적으로 불가능한 작업은 접고들어가야 할 것이며,끈임없는 타협의 시간이 될거 같습니다.
아쉬움이 많이 남지만, 아직 끝이 아니기에, 더 높은 완성도를 목표로 레이스를 완주 해야 할 것 입니다.

2017년 8월 2일 수요일

7월 28일

7월 28일
주간보고

지난 한주간 너무나 바쁘고 타이트한 스케쥴로 인해 보고서는 커녕, 잠조차 똑바로 자지 못했었습니다.

아직도 급한 사정은나아지지 않았기 때문에, 현제 프로잭트의 상태와 방향, 문제점들을 간단하게 언급 해 보겠습니다.


남은 기한은 한달입니다.
이제는 기능구현단계를 벗어나야 했습니다.
현실과 절충안을 위해 토의를 오랫동안 했으며, 우선적으로 적용된 기능을 기반으로 완성을 하도록 합니다.

첫번째 작업물은 아마도 :

 옷 입히기의 원시적인 형태
 캐릭터 커스터마이징의 원시적인 형태
 vr환경의 원시적인 형태

이 될것입니다.

이젠 정말 바쁜 한달이 될 것 입니다.

2017년 7월 23일 일요일

7월 21일

7월 21일
주간보고

이번 한 주간 또다른 무수한 고비들이 지나갔었습니다.
몇가지 해결된 사항과, 새로운 문제점, 장기적인 문제점 들이 나타났으며, 이를 하나 하나 이야기 해 보도록 하겠습니다.

VR 포팅

vr 포팅은 성공적으로 마무리 되었습니다. 일주일간 vr환경을 구현하는 방식을 리서치, 적용 시키면서 대부분의 일주일을 보냈는데, 아직까지 만족스러운 환경은 아닙니다.
예를 들어 이동에 관한 문제입니다.
팀장의 의견은 순간이동 방식의 캐릭터 이동에 매우 거부감을 가지고 있습니다.
컨트롤러를 의존해서 캐릭터 이동의 주장을 고수하고 있으며, 월드 좌표를 이용해 이동에 구현이 되었습니다.

하지만 월드 좌표의 기준이기 때문에, 캐릭터가 월드 좌표와 다른 방향으로 이동할때 생기는 문제가 나타나고 있습니다.

캐릭터 ver 1.3

캐릭터의 커스터마이징이 남은 한달간의 필수 과제입니다.
기초적인 적용방법 구현은 이미 성공했었습니다. 하지만 정확하고 빠른 계산방법은 다음 문제입니다.

캐릭터의 신체사이즈 조절은 본에 스키닝 된 부위의 scale 을 조절하는 방식입니다.

예를들어 목의 사이즈를 변경을 시도할시, 캐릭터의 목이라는 뼈에 인식되어있는 메쉬들의 사이즈를 변경하는 방식이지요.

여기서 하나의 문제점이 나옵니다.
스키닝 작업에서는 weight 추가작업이 들어갑니다. 특정 부위의 메쉬에 특정 뼈가 얼마나 커다란 영향력을 행사 할 수 있느냐 정도의 의미입니다.

이 말은 하나의 메쉬에 여러개의 뼈들이 조절을 담당 할 수 있다는 의미입니다.

목뼈를 조절하거나, 팔뼈, 심지어 발가락 뼈를 바꿀때도 메쉬는 그weight에 따라 얼마나 큰 영향을 받을 수 있는가를 결정 할 수있죠.
그 영향력은 0% ~ 100%까지 정할 수 있습니다.

이렇게 weight영향력을 얻은 메쉬들은 scale 값 ( 기본 1.0 배수)  을 가지고, 그 배수에 따라 알맞는 값들이 나오게 됩니다.

그럼 실제 메쉬의 사이즈(치수)는 어떻게 재는가? 인데, 이는 아쉽게도 재공하는 방법이 없다고 결론짓고 있습니다.

그렇다면 어떻게 치수를 재냐 인데요, 우선은 MarvelousDesigner 를 이용한 둘래를 얻는 방법을 이용했습니다.

마블러스에서는 캐릭터의 둘레 따위를 쉽게 잴 수 있습니다.

설명된 위의 방법들을 동원하여, 지금까지 치수화를 했었습니다.

완벽히 일치하지 않는 저급한 방법이었습니다.

그리고 이제 다시 막혔습니다. 스케일에 따라 변화되는 치수들을 재어, 정확한 신체치수의 변경이 되는지, 혹은 방안을 찾기 위해 시도 해 보았습니다. (1.0 스케일과 0.7 0.8 0.9 1.2 스케일일때의 둘레를 얻어, 값들의 증감폭을 구해보는 방식으로) 결과는 참담했습니다. 어떤 값에서는 무려 10센치나 넘는 오차가 발생했습니다.

이 부분을 해결하지 못하면, 커다란 문제를 갖게 되는것 입니다.

또다른 산이 코앞에 있습니다.

7월 20일

7월 20일
밤샘근무
캐릭터 신체 사이즈 조절에 대해 여러 논의끝에 추가 본을 여러개 심었습니다. 이로써 캐릭터 및 옷, 애니메이션의 제작업이 필요로 했었습니다.
이것이 수요일 마감 실패의 주 원인이였습니다.

이제 새롭게 만든 캐릭터가 배포준비가 되었습니다.
3d 메뉴 작업을 순조로이 진행했습니다.

새롭게 만든 캐릭터를 배포하며 나타난커스터마이징 문제가 생겼습니다.
금요일 보고서에서 다룹니다.

7월 19일

7월 19일
마감실패

밤샘근무를 했지만, 끝내 보여줄 만한 수준의 프로잭트 구현이 실패로 끝이났습니다.
금요일로 마감일을 연장받았으며, 추가적으로 알아낸 사실은 이러합니다.

HDMI 2.0 버전 혹은 DP 1.4 버전 혹은 이상이 아닌 케이블, 혹은 미지원 일경우 vr이 구현되지 않습니다.
그런 이유로 제 랩탑은 VR 구현이 불가능 합니다.(hdml 1.4 입니다)

데스크탑을 들고왔지만, minihdmi 포트 이외에는 구버전이었기 때문에, 구동에 실패했습니다.

케이블 주문을 했습니다.

7월 18일

7월 18일
포팅 작업 개시

non-vr 상태의 프로잭트를 vr프로잭트로 바꾸게 하기위한 작업이 시작되었습니다.
수요일까지 보여주는것이 목표이기 때문에 마음이 급한 상태 입니다.

vr과 언리얼 엔진간에 문제점을 발견했습니다. vr구동후 언리얼 작업 이외에 다른 앱을 실행시 언리얼에서 컨트롤러 인식이 되지 않았습니다.
해결법은 vr 제부팅 입니다.


7월 17일

7월 17일
VR 설치
VR 테스트용 룸 구현을 완료하고 실기 플레이를 하면서 대부분의 시간을 보냈습니다.

2017년 7월 16일 일요일

7월 14일


7월 14일

주간보고


아기다리고기다리던 주간보고의 시간입니다.


이번주에는 많은일들이 있었습니다.
일정에 맞게 계획을 바꿨으며, VR구매와 템플릿,캐릭터 신체 사이즈 조절 등 흥미로운 이야깃 거리들이 잔뜩 있습니다.

일정과 계획

마침내, 팀원들은 처음 목적과는 달리 약간의 계획변경은 불가피 하다는 결론을 냈습니다.
캐릭터의 신체에 맞는 자유로운 옷의 사이즈 조절은 남은 한달이라는 기간동안에는 너무나도 빠싹한 일정이며, 한달동안 완성 할 수 있을지 장담할 수도 없는 사항이기 때문입니다.
이러한 결정이 나고 곧바로, 팀장의 활약으로 프로토타입 캐릭터 옷입히기 기술을 적용했습니다.




VR 구매

드디어 Vive 를 구매했습니다.
대실도 완료했으나, 설정의 문제와 보안떄문에 설치가 완벽한 수준은 아닙니다.
이번주 중으로 룸을 구현할 생각입니다.

템플릿

당장 보여주기 위해 필요한 몇가지 에셋들을 구매할 예정입니다.
컨버팅 작업 의뢰를 했으나, 작업속도다 더딘듯 합니다. 이번주 초 까지 통보를 못받는다면 다시 컨택을 해봐야 할 듯 합니다.

캐릭터 업데이트 #1 

프로토타입으로 만들었던 mimi chan 의 기본적인 형태는 변함이 없지만, 약간의 뼈 추가, 혹은 스키닝 작업을 위해 지속적으로 디자이나와 의뢰를 주고받으면서 시간을 보내고 있습니다. 캐릭터가 완변해야만, 작업이 올바르게 작동됩니다. 이는 매우 중요한 사항입니다.




옷 추가를 위한 초석, Marvelous Desinger

이미 디자이너는 Marvelous Desinger 를 배우고 있었습니다만, 이제서야 여러종류의 옷을 만들어 볼 시간적 여유가 생겼습니다. 그러기 이전에, 우리 캐랙터인 mimi chan 에 맞게 만들기 위해 Marvelous 에 맞는 mimi 아바타를 생성해야할 이유가 생겼었습니다.
타입은 여러가지를 만들 수 있었지만, 지금 당장은 기초 아바타면 충분 할 것 입니다.


 (아바타 작업을 완성한mimi chan 입니다)



신체사이즈

size matter! 현제 제가 맡고있는 주 파트입니다.
캐릭터의 신체 세분화 작업이 완료되었고, 부위별 조절기능을 한번더 숙지했으며, 자료구조와, 약간의 사이즈 조절 알고리즘을 만들었습니다. 이 알고리즘은 다행스럽게도 여러 타입의 신체구조 혹은 부위를 그나마 손쉽게 추가 수정 할 수 있을것이라고 평가 중 입니다.


 (끔찍한 수준의 방대한 노드들, 최적화는 필수일 것 입니다)


이 작업들을 통해 알아낸 몇가지 사실은
unreal에서 Map 을 지원하지만, 수정이 불가능 합니다.
unreal에서는 다차원 자료구조를 사용할 수 없습니다.
unreal에서는 기본 1uu=1cm 이며, 스케일링은 배율로 계산합니다.

우리팀 역시 cm단위를 기본으로 하며, 이에 맞게 반응되도록 식을 BP로 만들었습니다, 이에 따른 계산 속도는 느릴것으로 예상되며, 작업 안정화가 되었을 때에, 코드화 구현이 필수적인 파트가 될것 입니다.

다차원 자료구조가 먹히지 않는다는 사실이 가장 큰 충격이었으며, 이로인해 굉장히 비효율적인계산구조를지니고 있습니다. 이부분 역시 배포 전 수정해야할 부분입니다.


마치며

이제 팀은
프로토타입 캐릭터의 완성
프로토타입 애니메이션 생성
옷 추가
템플릿 구매/ 생성
텍스쳐와 머티리얼 작업
사이즈 작업 마무리
VR 환경 준비

등의 작업이 진행될 것 입니다.
다음 한 주는 끔찍히 바쁜 주말이 될 것 으로 보입니다.
하지만 드디어, 조금씩 성과가 보이기 시작하기 때문에 팀원의 사기는 더욱 증진한거 같습니다.

이제 한달 채 남지 않았습니다.
멈출 여유또한 없습니다.



2017년 7월 13일 목요일

7월 13일

7월 13일

어느정도 순조로운 진행

마블러스 디자이너에서 캐릭터 에셋 생성의 기초는 끝이났습니다.
어느정도수준의 이해는 되었기에 심화 작업을 요청받아도 금새 끝낼 수 있을것 입니다.





e
디자이너에게 스키닝 작업의 중요성을 이해시켰습니다. 동영상의 캐릭터의 전면부는 현제 애니메이션 행동시 가슴팍에 끼이는 문제가 발생합니다.

이를 해결하기 위한 현제 최고의 솔루션은 스키닝의 완벽한 작업입니다.
디자이너가 비명을 지르더군요.

수치를 위한 계산식이 필요합니다.
우선 첫번째 캐릭터의 기본 신체부위 둘레를 얻었습니다.
이를 이용해 디테일한 신체변화를 하는 방법을 찾아야 합니다.





2017년 7월 11일 화요일

7월 12일

7월 12일

환기



작업의 노선을 바꾸고, 팀장이 제시한 방법의1차적인 정상동작을 확인했으며, 추가적인 확인작업을 기다리고있습니다.

vive를 구매했습니다. 배송을 받고 곧바로 vr ready 를 준비할 예정입니다.

옷 사이즈에 대한 수치 조절을 구상중 입니다.

옷 디자인을 위한 마블러스 디자인에서 아바타 생성을 맡았기 때문에 작업을 진행 중 입니다. 첨부사진이 작업중인 사진입니다.

7월 11일

7월 11일

도움을 받다.

어젯밤 Player Unknown Battleground 의개발팀원중 한명과 잠깐의 대화를 통할 수 있었습니다.
우리의 목표를 설명했을때  납득을 하는것으로 보아 역시 이 작업이 불가능한 수준은 아니라는 판단이 들었습니다.

힌트를 몇개 얻어서, 자신감이 생겼습니다.

또한 팀장의 성과가 보이기 시작하기 때문에,시도해볼 것들이 다시 더 생겼습니다.

오후에 강사님의 힌트를 얻어서 몇가지 해결하지 못했던 인터페이스 구현 방법의 실마리를얻었습니다.

야간시간에, 팀회의를 거쳐 우선사항의 변경을 결정했습니다.

1. 옷에 대한 현실적인 물리시스템은 현제상태에서 pasuse 를 한다. 계속 진행하기에는 시간 낭비가 심각하다.
2. vr ready 를 준비한다.
3. 수치 조절 알고리즘에 대해 작업을 시작한다.
4. 머티리얼과 옷 메쉬 제작을 시작한다.

로 내일부터 방향 전환을 시작합니다.

지금 하던것들은 분명 작업중에 새로운 힌트나 아읻어를 받을 수 있을 것 입니다.

너무 오래 지체했습니다.
죽이든 밥이든 나아갈 시간 입니다.


7월 10일

7월 10일

소득없음

수요일이 점검일로 확정이 되고, 디자이너와 함께 실험실에서 보냈습니다.

특별히 별다른 소득은 없었지만, 코드 분석을 오랫동안 했기 때문에, 결코 아무것도 하지 않은것은 아니라는 자위를 합니다.

2017년 7월 9일 일요일

7월 7일

7월 7일

주간 보고  

일주간 일어난 성과나 문제점을 다시 정리해 봅니다.

여전히 옷입히기


여전히 옷입히기 기능에서 문제를 겪고있습니다. 지난주와 같은 상황에 있습니다. 옷이 줄어들지는 않지만, 콜리전또한 바뀌지 못하고 있습니다.

디자인 파트의 일시중단, 협업


디자이너의우선작업 가능한 파트가 끝이났습니다.
약간 상의끝에 엔진파트에 같이 붙기로 정했습니다.
만 하루끝에 디자이너와 저의 갭을 해소했으며, 새로운 방식들을 생각 해 낼 수 있었습니다만, 아직까지도 얻은것은 없었습니다.

다시 코드로


디자이너와 이야기를 거친후,
저는 디자이너에게 추가적인 조사를 부탁하고 코드로 넘어가야한다는 개인적인 판단을 내렸습니다.

우선 블루프린트 네이티브화 라는 기술을 알아봤습니다.
블루프린트에서 작업된 코드를 c++로 변환시켜 이중 작업을 용의하게 만드는 기술인것 같습니다만, 아직까지 c++에서 블루프린트로 바꾸는 기술에 대해서 얻은 정보가 없으며, c++코드로 변환시 일어나는 문자열 정렬 문제도 있기때문에 우선사항에서 밀려났습니다.
블루프린트 네이티브화

에디터를수정하면 어떨까 하는 방안을 떠올렸고, clothing 시스템의 위치를 파악했지만, 간단히 코드 교체로는 변화가 있지 않았습니다.

제조사 및, c 코드 공부를 다시 시작해야겠습니다.

2017년 7월 6일 목요일

7월 6일

7월 6일
디자이너의 도움
더이상 디자인 파트의 작업의 진행이 불가능하기에, 엔지니어링과 협업을 하기로 했습니다.
완벽하진 않지만 인수인계가 성공적으로 끝났고, 내일부터 정석적으로 협업을 들어갈것 입니다.

7월 5일

7월 5일
전진이 없음..

디자이너의 작업진행의 진행이 불가능하게 되었기 때문에,
제가 겪고있는 문제에 같이 붙어서 문제의 원인을 찾기 시작해 보고있습니다.
성과는 아직 없지만, 몇가지 더 새로운 시도방법을 얻을수 있었습니다. 혼자보다는 역시 좋군요.

7월 4일

7월 4일

잠깐 쉬어가기

디자이너와 상의중 마야에서 발생하는 조그만 문제를 해결하기 위해 협업을 했습니다.
결과적으로 스두스 라는 마야의 기능을 올바르게 언리얼 엔진으로 가져오는방법을 배웠습니다.

옷입히는 작업은 여전히 제자리걸음..

2017년 7월 3일 월요일

7월 3일

7월 3일

진행상황



physicsAsset 을 공유하는 방법을 찾았다고 판단했으며 실제적으로 입혔으나 아직까지, 이게 진짜 적용이 된건지 애매한 상황입니다.
디버깅으로 플레이시, 렉돌의 사이즈가 일정 수치 이상 혹은 이하가 되면 더이상 스케일링이 되지 않고, 겹치거나 붕 떠버리는 현상이 있습니다.

추가적으로 알아낸 사실 이 몇가지 더 있는데
1. 14년까지만 해도 에픽사에서는 본 스케일링을 권장하지 않았으며, 지금도 권장하는 편은 아닌듯 하며.
2. 실제로 본 스케일링이 적용된 사례를 보았을때, 피직스 판정범위는 올바르지만 동적으로 40마리 정도의 적이 움직이는 게임에서 상당한 퍼포먼스 하락을 봤습니다. 문제가 있다는것은 명확해졌습니다.
3. 현제 상태에서는 옷이 올바르게 적용되어 보이지는 않습니다.
4. 옷이꽉 조이는 효과는 보이기 힘듭니다. 왜냐하면 메쉬의 찢어짐 효과는 현제 게임에서구현하기가 곤란하다고 판단됩니다. 물론 APEX Distruction 같은 기술은 있으나, 우선사항은 아닌거 같습니다.

2017년 7월 2일 일요일

일지작성

비공개로 작성중이던 일지를 읽을 사람도 없으니, 추가 수정없게 하기 위해 바로바로 작성하기로 판단했으므로, 특별한 일이 없는한 꾸준히 업데이트를 해야할 것!
잊지말자, 니미래를 위해서야

6월 30일

6.30
주간보고

지난 이주간 팀원들의 작업현황을 보고합니다.

우선 모델링 파트에서는 커다란 성과를 보였습니다.



올바른 rigging 과 skinning 그리고 간단한 animation 제작방법을 터득한 디자이너는, 목요일날 배포가능한 캐릭터의 리깅과 스키닝을 끝냈습니다.
이 말은 이제 본격적으로 보여 줄 만한 캐릭터를 이용해 작업을 진행 할 수 있다는 의미입니다.
올바른 rigging을 왜 준비하는데 오래걸리냐 는 질문이 있을 수 있습니다.
다른 사이트 등에서 쉽사리 기본제공해주는 뼈들이 잔뜩 있으며, auto  rigging tool 역시 흔하게 존재하는데 말이죠.

저희는 일반적인 게임이 아닌 시뮬레이션 이기 때문에, 기존에 사용하는 뼈의 개수만으로는 상당히 부자연스러울 수 있다는 결론을 얻었기 때문에, 힘들지만 처음부터 maya 공부를 진행하게 되었습니다.

이 말은 곧 애니메이션 또한 처음부터 작업을 해야한다는 말 이기도 하죠.
분명 힘들지만 커다란 성과인 것은 확실하다고 판단중입니다. 디자이너의 이주간의 노고의 결과는 조금더 미래에 나오겠지요.



다음으로는 엔진 파트입니다.

언리얼 엔진의 기본적인 작동 메커니즘과 코드의 사용방법 등을 공부하며, 동시에 필요한 물리에셋의 복사방법을 찾기 위해 아직도 작업중인 단계입니다.
개발속도가 너무 늦기 때문에, pause를 해야하나 걱정을 했지만, 어느정도 성과가 나오고 있기 때문인지, 윗선의 압박이 조금 줄었습니다.

동시에 처음에는 문제없다고 판단했던 본 스케일링 파트는 추가적인 고민거리가 생겼습니다.
본 스케일링시 자식 본 마저 같이 스케일링 된다는 사실입니다.

과연 이 행위가 우리에게 더 이로울지, 아니면 독이 될지 판단을 하고, 해결방안도 미리 구해 놔야 할 것 같습니다.

이 부분을 해결한다면, 다음으로 걱정해야 할 파트는 알고리즘입니다.
캐릭터의 신체사이즈와 옷의 사이즈간의 상관관계와 그에따른 올바른 옷을 꺼내는 작업에 대해 고민을 시작해야할 때 인 것 같습니다.

현제 APEX cloth 기술에서는 옷의 질감에 대한 상세설정은 없다는 추측을 가지고 있기 때문에, 미세 값에 따른 올바른 옷 추천이 무엇보다 중요해진게 아닐까 추측하고 있습니다.
신축성의 유무에따라 추천하는 옷의 범위도 바뀔것이 분명하기 때문에, 고려해 주어야할 변수들이 상당할 것 이며, 이에따른 sort 처리속도 또한 늘어날 것입니다.

옷에 집어넣는 올바른 physics Asset은 조금더 연구가 필요하지만 성과가 없는 것은 아닙니다.

하지만 그렇다고 이곳에 현제 상태를 적자고 하기에도 애매한 상황이군요. 검증이 필요한 단계입니다.
월요일이나 화요일에 검증의 결과를 얻어야 할 것입니다.
더 정확히 할 수 있을거 같습니다.

전체적으로 느리지만 전진이 없지는 않았던 한달입니다.
종합적으로 보면 늦고있습니다. 조금더 박차가 가해졌으면 합니다.

6월 29일

6.29 
more about c++
 
지난 날의 결과는 아직 부족하다는 결론이 났습니다. 포인터 세팅의 문제는 아니라는 확신이 들었습니다. 에셋을 잘못된 위치에서 들고왔다는 생각이 지배적입니다.

조금더 기초로 돌아가 하드코딩으로 캐릭터 생성부터 시작해서 코드의 작동순서를 파해쳐야 피직스 에셋의 작동원리를 좀 더 정확히 할 수 있을거 같습니다.

6월 28일

6월 28일

code it






마침내 코드의 리버스 엔지니어링을 통한 분석을 손을 댈 수 있을정도로 되었기 때문에, 추측에 따라 첫 번째 피직스 에셋 복사 작업을 시도했습니다.

우선은 블루프린트 노드를 생성했으며, 두 개의 스캘래탈 메쉬의 피직스 에셋값을 받아오며, 받아온 값들은 함수를 통해 복사하는 작업을 시도했습니다.

코드들의 작동은 성공적이었으며, 오류또한 없었지만, 실제로 사이즈의 변형은 일어나지 않았습니다.

이로써 추측할 수 있는 것은 두가지 인데,
1 . 포인터 사용에 실수가 있었다.
2 . 피직스 에셋을 가져오는곳이 틀렸거나, 전혀 엉뚱한 부분의 에셋을 골랐다.

정도로 평가 할 수 있을 거 같습니다.

실패했지만 그럼에도 약간 자신감도 돟아올 수 있었습니다. 실제로 코드를 삽입했고 컴파일까진 됬으니깐..

6월 27일

6.27
ongoing c++ 

막다른길 에 도달한게 아닐까 싶어지는 순간이 찾아왔습니다.
맨땅에 삽질도 정도껏인데, 끝이없다는 생각이 자꾸 든다는 기분이 드네요.

살찍 팁을 얻을 수 있지 않을까 싶어 방향은 조금 다르지만, 그래도 프로그래밍 쪽에서 지인 실무자에게 문의를 구했고, 돌아온 답변은 내가 하고있는 방식이 슬프지만 유일한 방법이라는 위안같지않은 위안을 얻었습니다.

오늘 종일 확신을 가지고 파고있던 소스파일은 결국 다른 작업물의 파일이라는 사실을 알았지만, 동시에 어떤 작업에 필요한 소스파일인지 알아내는 방법을 얻었기 때문에, 완전히 의미 없는 성과는 아니게 되었습니다.

하지만 이야기가 되었듯이, 이제 시간이 그렇게 많지 않습니다. 고 스톱, 어느쪽이든 이제 정해야 할 시기가 다가옵니다. 시간을 더 달라고 하고싶지만...

6월 26일

6.26
여전히 c++
 
여전히 답변은커녕 강의조차 찾지 못하고있기 때문에 불안감은 최고조에 달하고있습니다.
불안감을 어떻게든 해결하기 위해 되든 안되든 강의를 따라하고있으며, 어느정도 이해는 되기 때문에(강의의 절반은 구버전이기에 따라할수 없는 수준이지만) 그나마 위안을 삼고있는 수준.

수많은 SkeletalMesh들

c++ 코드속에서 드디어 원하는 Skeletalmesh를 찾은 듯 했으나, 이는 곧 9시즘 수많은 Skeletalmesh중 하나일 뿐이라는 사실을 알았습니다. 이중에 내가 원하는게 있는지 조차 문제지만..이 수많은것들ㅇ르 하나 하나 테스트하는것도 일인거 같습니다.

quick note:
Engine – UE – plugins – Runtime – ImmediatePhysics – public – BomeControllers
수상한 부분, 이건 4.16버전의 새로운 물리 기술, 당장 그다지 중요한 부분은 아니네요











6월 23-24

6.23

about code



대부분의 C++ 코드 강좌는 매우 구버전이며, 수없이 바뀐 함수들과 작동방식 때문에, 강의를 따라가는 것은 불가능에 가깝다는 결론이 났습니다.

금요일 토요일 은 집중적으로 따라 할 수 있는 c++ 강의와 현제 문제에 대해 다른 접근방법을 알기 위해 리서치 및 질문을 하는 시간뿐 이었습니다.

진도가 나가지 않아서 극도의 불안감이 따라오며, 더더욱 집중이 되지않기에, 주말은 날렸습니다. 애헤라디야

6월 22일


6월 22일
에디터를 에디트하기 위한 에디터






언리얼엔진에서 제공하는 full source로 처음에는 어디서부터 어떤기능을 재공하는지 몰랐지만, 이제 필요한 시기라고 판단하여 설치를 했습니다.
그리고 드디어 알아낸 사실은 이러했는데 : “언리얼엔진을 수정할 수 있는 소스코드들“
이었습니다.
설치부터 하나의 난관이었기 때문에, 재법 시간을 소모했었고, 이제 기초부터 빠르게 해치워 나가야할 시간인 것 같습니다.


비트수업 에서는 가볍게(혹은 내가 안들었거나) 지나갔던 헤더파일과 cpp파일의 차이를 명확하게 해야했습니다.
헤더파일은 마치 자바의 인터페이스같은게 아닌가 싶더군요. 사용할 함수를 미리 형식을 다 정해놓고 적어둔 뒤, 사용할 함수들을 소트시켜 같은 종류끼릴 묶어둔 놈을 헤더라 보면 될거 같았습니다.
물론 헤더에 함수내용을 입력해도 되지만, cpp파일에서 include 된 헤더가 나올때마다 해당 헤더를 읽게되는데, 이때 내용물에 함수내용이 들어가 있다면, 그것들을 모조리 읽어내기 때문에 컴파일 시간이 길어지는 문제점이 일어 날 수 있기 때문에 그러지 않는 것이 옳은 방법이라 합니다.

quick note:
U : low API수준의 언리얼 언어
A: 객체들을 의미. 매쉬나 파티클 음향효과...etc
S : slate, UI관련
F : 구조체 structure

6월 21일

6월 21일
skinning





명백히 당장은 쓸모없는 기능이라고 생각되지만, 언젠가는 해야할 공부를 어제 시작했었습니다. 진도도 더 이상 안가가고 자신감도 많이 떨어져 있었기 때문에 비교적 즐겁게 배웠으나, 이로써 역시 3d max 로 스키닝 작업은 미친짓이라는 결론을 얻었습니다.
스키닝의 기초 개념과 사용법, 그리고 어느정도 수준의 APEX로 질감구현의 방법을 터득하기도 했기에, 완전히 무의미한 시간은 아니었습니다.
어제 알아낸 기술인 nCloth는 우리 프로젝트에서는 크게 쓸모가 없다는 결론을 얻었습니다.
nCloth 는 Maya에서 고유적인 스크립트로 작동하는 애니메이션 부가기능인데, 이것을 추출 할 수 는 있으나, 단지 미리 baked 된 애니메이션만을 가져올 수 있다는 제한이 있었습니다.
 그 말은 모든 애니메이션, 옷, 캐릭터에 따른 nCloth를 미리 구워서 들고와야 한다는 의미이며, 시간과 자원을 터무니없이 많이 쓸 것 이라는 이유입니다.

















본 컨트롤러 구현










운 좋게도 올바른 캐스팅 방법을 찾아내어 본 컨트롤러의 구현을 성공했습니다.
이로써 캐릭터 커스터마이징은 전부 구현가능으로 결론지었습니다.

이로써 한가지 더 확정된 사실은, 본과 피직스 에셋을 공유를 해도, 본 혹은 피직스 에셋이 바뀐다 한들 다른 메쉬에서는 영향이 없다는 사실입니다. 당연한 이야기였지만 단계별로 알아가기 위한 수준이라고 생각합니다.
이로써 c++코드 사용이 더더욱이 필요하다는 생각에 힘이 들어갑니다.
또 동시에 방향도 조금 더 구체화가 된 것이, 스켈레탈 메쉬를 생성할때에 참조 혹은 동적 메모리로 생성할 본과 피직스 에셋을, 공유하는 방식으로 전환하는 방법을 찾아야 한다입니다.

가능여부는 물론, 실제 구현시 일어날 다른 문제점들도 분명히 있겠지만, 적어도 지금 당장 시도 해 볼 방향은 이것인 것 같습니다..

6월 20일

6월 20일
nCloth 와 옷 모델링 등장 







지난 회의로 시아를 환기시켰으며, 덕분에 조금 더 절망스러워졌으나, 다행히도 모델링 파트에서 커다란 전진을 보였으며, 또 새로운 실마리 또한 던져줬기 때문에, 시도해 볼 것들이 다양하게 늘어났습니다.

1. 남성용 상의 옷 모델링 두벌 셈플을 받음.
2. nCloth 기술을 들었음

이로써 시도해볼 방향은
1. physX Asset의 동적인 변화가 Apex Cloth 에 적용이 되는가?
    - 블루프린트 작업으로 우선 시도해 볼 것.
    - C++ 코드로 asset 부분을 포인트 하는 방식은 어떨까?
2. Maya nCloth 기술을 시도 해 볼 것.
    - 시범적용
    - 실현가능성 따지기.

가 생겨났으며, 하나씩 막힐때마다 바꿔가며 알아보고 있는 중입니다.

당장 nCloth에 대해 리서치 했을 때 나온점들은..
1. APEX를 unreal 에서는 지원하고 있다.
2. nCloth를 위한 Geometry Cache 역시 지원하기 떄문에, nCloth에 대한 배려가 없지는 않다.
3. nCloth 는 physiX Asset의 regdoll 이 필요없다?(조금더 알아봐야 할 것)
4. nCloth는 pre rander가 필요한 애니메이션일 뿐이다?
5. geometry cache 방식을 사용하지 못한다면 Morph target을 이용해야한다.
6. 부드러운 천을 APEX보다 월등히 잘 표현 해냈다.

정도 인듯합니다. 리서치가 더 필요한 부분입니다.


6월 19일

6월 19일
돌아가는 시간








피직스를 건드릴 계획은 잠깐 미뤄두기로 했습니다. 현제 목표를 잠깐 바꾸어 본 트렌스폼에 우선적으로 생각을 해보기로 결정했습니다.

우선 지난주에 알아낸 새로운 실마리는 본 컨트롤을 할 경우 피직스 랙돌 범위또한 늘어난다는 정보를 얻었으나,
하지만 옷을 늘릴 수 있다 한들, 옷의 치수가 바뀌면 안되기 때문에 옷에 본 컨트롤을 입힐 이유가 하등 없다고 개인적으로 판단중입니다.

APEX를 적용시킬 때 덮어씌울 피직스 에셋은 별도로 지정이 가능했었기 때문에, 만일 사람의 피직스 에셋을 지정한뒤, 사람의 신체사이즈를 조정한뒤 반응은 어떠할까 라는 의문을 가지게 되었습니다.

이를 실험해 보기 위해 이론뿐이었던 캐릭터 본 스케일링을 실제로 구현해야 할 시기라고 판단 되었고,

이후 오후에서 추가적으로 회의를 거쳤으며, 아직까지는 판단이 명확하게 서지는 못했으나, 무엇이든지 밀어봐야 할 시기가 되었습니다.

6월 16일

6월 16일
APEX Cloth 와 Unreal Engine4





Unreal의 최신버전인 4.16 의 쇼케이스에서 새롭게 선보인 기능들이 몇 개있는데, 그중에서 Unreal 자체 엔진에서 APEX Cloth 기능을 내장시켜벼렸습니다.
특히 clipping 문제등이 골칫거리였으며, maya 혹은 max에서 작업한 결과물이 Unreal 에서는 올바르게 나타나지 않는 문제들이 있었는데, 이를 해결하기 위함이라고 합니다.

4.16에서 experimental 기능에 “Clothing tool“를 활성화 시키면, 메쉬 수정단계에서 작업을 진행 할 수 있는데, 이미 사용하는 엔진이며, 기능도 단순하기 떄문에, max에서 작업환경때 보다 수월하고, 더 빠르게 결과물을 볼 수 있는 장점이 있었습니다.

또 이로써, 언리얼에서 제공하는 phAT 의 physX를 ragdoll로 인식시켜 physX에셋툴을 재사용의 편의성이라는 매우 큰 장점을 얻어냈습니다.

이로써 생각 해볼 부분들이 약간 변환되었습니다.

1. 랙돌의 사용방법과 cloth적용방법이 간편화 되었기 때문에, 이제 랙돌의 동적인 변화방법을 구현시키면 될 것.

2. socket이나 mesh 겹치기 방식은 완벽한 솔루션이 아니기 때문에, 더 좋은 방법이 있는지 찾아볼 것.

3. 옷에 대한 올바른 물리효과 기대치를 찾아낼 것

정도로 지금은 나눌 수 있을 것 같습니다.

6월 15일

6월 15일
현제까지 밝혀진 문제점/공부할 점

현제 내부에서 핵심 기능으로 평가중인 옷 과 신체사이즈 간의 관계, 사실적인 물리효과
에 대한 정보를 업데이트 합니다.
크게 핵심기능과 문제점을 짚어보며, 2주차 발표 이후 우리가 넘어가야 할 첫 번째 산이 어느 파트인지 설명 해 보겠습니다.




핵심기능과 문제점


1. 첫 번째로 신체사이즈는 Morph targer 과 Animation bone controller를 사용하여 키와 살의 변형이 가능하다는 결론을 얻었고, 이미 Morph target은 실제 적용에 성공하였습니다. 애니메이션 파트를 맡기에는 아직까지 시간과 정보가 부족하며, 우선순위도 비교적 낮기 때문에 2주차 발표에서는 구현 단계를 미루기로 결정했습니다.










(Morph target을 이용한 캐릭터의 세부적인 표현)








2. 두 번째로 옷에 대한 사실적인 물리효과에 대한 것입니다.
지금까지 AMD 와 NVIDIA, 혹은 HAVOK 사 등에서 내놓은 여러 가지 물리 엔진이 있으나, 얘나 지금이나 모델링 Clipping 문제가 있습니다.








 (위쪽의 AMD hairworks   아래쪽의 NVIDIA사의 Gameworks)


현제 코드빼고 무료로 공개되어있고, 다른 엔진에 비하여 양호한 편으로 Clipping문제를 해결중 이며, 좋게 평가 받고있는 Nvidia 사의 APEX Cloth 시스템을 사용하기로 결정했습니다.





(APEX Cloth)




기초적인 Cloth 시스템의 구현 역시 성공적으로 되었습니다만. 아직 남아있는 문제가 있습니다. 옷에 대해서는 ragdoll 시스템을 주입시켜야 합니다.




(ragdoll과 애니메이션의 병합 예시, ragdoll 수치를 높게 잡아 애니메이션에 따라 휘두른 주먹의 힘의 양이 메쉬의 몸무개를 뛰어넘어버려 메쉬는 넘어지게 된 장면입니다.)


ragdoll의 초기 구현 목적은 애니메이션과 별개로 스스로 “물리”적으로 동작하는 메쉬를 위해서 만들어 졌습니다.
이후 오랫동안 발전 끝에, 이 기술은 애니메이션 시스템과 병합되거나, 독립적으로 높은 퍼포먼스를 유지하며 훌륭하게 동작하는 단계에 이르렀습니다만, 독자적인 시스템들이 들어간 아종 ragdoll 들이 많이 생겨, 기준이 애매한 상태인 것 같습니다.

APEX Cloth 시스템에서는 ragdoll을 사용한다고 명시하였으며,
언리얼 엔진에서는 phAT라며, 물리에셋툴 이라는 이름의 툴을 이용해서 ragdoll과 비슷한 물리를 사용중인 것 같습니다.
14일 오전 테스트로 APEX Cloth 에서는 phAT 의 ragdoll은 먹히지 않았습니다.
같은날 오후 테스트로 APEX Cloth에서 사용하라고 하는 ragdoll을 구현했을 때, 정상적으로 언리얼엔진에서도 인식이 되는 것을 확인했습니다.

이로써 해결해야 하는 문제는 아래와 같습니다:
1. APEX의 ragdoll 시스템과 Unreal에서 제공하는 ragdoll 시스템은 동일한가?
2. 동일하다면 unreal에서 제공하는 ragdoll 로 APEX의 옷에 기능을 적용 할 수 있는가?
3. 동일하지 않다면 동일하게 바꿀 수 있는가?
4. 체형의 변화에 따라 옷에도 적용해야할 ragdoll 범위또한 변해야 한다. 이를 해결하기 위한 솔루션이 있는가? 혹은 C++ 코드로 우리가 수정 할 수 있는가?

의 문제가 남아있습니다.



3. 세 번째의 문제인  옷과 신체사이즈 간의 관계입니다.
신체사이즈의 조절과 기획에 맞는 옷의 사이즈를 생각하여 낸 결론은 문제없다 압니다.

우선 이 작업을 시작하기 앞서, 우리는
1. 수정을 할 신체부위의 최소, 최대치 기준 정립.
2. 옷과 신체부위와의 비교가 필요한 부위를 결정.
3. 옷과 신체부위의 메쉬와 언리얼 엔진에서의 치수 통일 ex) 1uu=1cm
4. 옷의 사이즈, 재질, 부위별로 세분화, 그에따른 신체에 적용가능한 허용 수치 결정.

를 회의를 통해 최종 정립합니다.

이후 신체사이즈에 따른 올바른 옷들을 sort 시켜줄 수 있는 알고리즘을 구현합니다.







가장 우선적인 작업



이 작업들을 행하기 위해 가장 중요한 부분은 통일되고, 필요기능이 충족되고, 재사용이 용이한 뼈대인 스켈레탈 메쉬를 구현하는 것입니다.
스켈레탈 메쉬가 있어야만 올바르게 아바타 생성, 옷과 아바타사이의 현실적인 적용, APEX 적용이 가능하게 되기때문에 가장 우선적으로 작업되어야 할 부분이 될 것입니다.
이미 이 부분을 맡을 Maya 공부는 시작되었습니다.