728x90

다운로드 : https://opencv.org/releases.html


들어가서 원하는 버전을 받으면 된다.


설치하고자 하는 폴더에 설치를 한다.


설치후 환경 변수의 Path에 설치한 경로를 추가해준다.


설치는 완료되었으니 이제 프로그래밍을 시작하면 된다.


728x90

'Visualization Programming > OpenCV' 카테고리의 다른 글

OpenCV - Helloworld  (0) 2018.09.01
OpenCV - 개요  (0) 2018.09.01
728x90

Image Processing은 컴퓨터를 이용하여 입력영상을 보다 질 좋은 출력영상으로 얻는 과정이다. 예를 들면 포토샵을 이용하여 입력영상에 포함된 noise를 제거하거나, 영상의 대비를 개선하여 더욱 선명하게 하는 과정, 영상의 특정 부분을 강조하거나, 관심영역을 분할 하고 영상 파일로 압축하여 저장하는 과정등을 모두 영상처리라고 한다.


Computer Vision은 카메라에 의해 획득되는 입력영상으로부터 의미 있는 정보를 추출해 내는 분야로 주로 실시간 응용프로그램에서 많이 다루고 있다. 예를 들면, 산업현장에서 자동으로 제품의 결함을 검사하거나, 스캐너 또는 카메라로 획득한 영상에서 문자인식, 얼굴인식, 지문인식, 사람 또는 자동차 등과 같은 움직이는 물체 검출 및 물체 추적 등을 모두 컴퓨터 비전이라고 한다.


영상처리와 컴퓨터 비전은 모두 영상을 처리하기 때문에 많은 내용이 중복될 수 밖에 없다. 대략적인 구분으로는 컴퓨터를 사용하여 영상을 처리하는 모든 분야를 영상처리라고 하고, 인간의 눈 대신 카메라에 의한 영상을 입력하고 인간의 뇌 대신에 컴퓨터를 사용하여 영상으로부터 의미 있는 정보를 추출하는 분야를 컴퓨터 비전이라고 생각하면 된다.


OpenCV(Open Computer Vision)은 컴퓨터 비전용 무료 라이브러리이다.


즉, OpenCV는 영상처리, 비디오처리, 기계학습, 컴퓨터 비전 관련 라이브러리로 소스가 공개되어 있고, BSD 라이선스를 따르며, 교육 및 상업 목적의 사용이 모두 무료인 라이브러리이다.



728x90

'Visualization Programming > OpenCV' 카테고리의 다른 글

OpenCV - Helloworld  (0) 2018.09.01
OpenCV - 설치하기  (0) 2018.09.01
728x90

HowTo_Programming-201805.pdf


올해 5월에 나온 자료다... 한번쯤은 읽어보고, 모르는 단어나 용어가 있으면 찾아서 읽어보면 좋을 것 같다.

728x90
728x90
1. constexpr


기존의 const 보다 훨씬 더 상수성에 충실하며, 컴파일 타임 함수를 이용한 성능 향상 등 충분히 깊게 이해할만한 가치가 있는 녀석이라 할 수 있으니, 확실히 이해하고 활용할 수 있는 것이 중요하다.

C++11부터 지원되는 한정자 constexpr는 일반화된 상수 표현식(Generalized constant expression)을 사용할 수 있게 해주며, 일반화된 상수 표현식을 통해 변수나 함수, 생성자 함수에 대하여 컴파일 타임에 평가될 수 있도록 처리해 줄 수 있다.
(C++17부터는 람다 함수에도 constexpr 키워드 사용이 가능하다)

constexpr 변수 또는 함수의 반환값은 반드시 LiteralType이어야 하며, LiteralType은 컴파일 타임에 해당 레이아웃이 결정될 수 있는 타입을 의미한다. 다음은 리터럴 타입들의 유형이다.
  • void
  • 스칼라 값
  • 참조
  • void, 스칼라 값, 참조의 배열
  • trivial 소멸자 및 이동 또는 복사 생성자가 아닌 constexpr 생성자를 포함하는 클래스. 또한 해당 비정적 데이터 멤버 및 기본 클래스가 모두 리터럴 타입이고 volatile이 아니어야 함

코드 작업 중 해당 타입이 리터럴 타입인지 확인하고 싶을 땐, std::is_literal_type을 사용하면 된다.


1) 변수에서의 사용

const와 constexpr의 주요 차이점은 const 변수의 초기화를 런타임까지 지연시킬 수 있는 반면, constexpr 변수는 반드시 컴파일 타임에 초기화가 되어 있어야 한다.
초기화가 안 되었거나, 상수가 아닌 값으로 초기화 시도시 컴파일이 되지 않는다.

  1. constexpr float x = 42.f;    // OK
  2. constexpr float y { 108.f }; // OK
  3. constexpr int i;             // error C2737: 'i': 'constexpr' 개체를 초기화해야 합니다.
  4. int j = 0;
  5. constexpr int k = j + 1;     // error C2131 : 식이 상수로 계산되지 않았습니다.

변수에 constexpr 사용시 const 한정자를 암시한다.


2) 함수에서의 사용

constexpr을 함수 반환값에 사용할 때는 다음의 제약들이 따른다.
  • 가상으로 재정의된 함수가 아니어야 한다.
  • 반환값의 타입은 반드시 LiteralType이어야 한다.

함수에 constexpr을 붙일 경우 inline을 암시한다.
즉, 컴파일 타임에 평가하기 때문이며, inline 함수들과 같이 컴파일된다.

C++11에서는 함수 본문에 지역변수를 둘 수 없고, 하나의 반환 표현식만이 와야 하는 제약이 있었으나, C++14부터는 이러한 제약이 사라졌다.

  1. // C++11/14 모두 가능
  2. constexpr int factorial(int n)
  3. {
  4.     // 지역 변수 없음
  5.     // 하나의 반환문
  6.     return n <= 1 ? 1 : (* factorial(- 1));
  7. }
  8.  
  9. // C++11에서는 컴파일 에러 발생
  10. // C++14부터 가능
  11. constexpr int factorial(int n)
  12. {
  13.     // 지역 변수
  14.     int result = 0;
  15.  
  16.     // 여러 개의 반환문
  17.     if (<= 1)
  18.         result = 1;
  19.     else
  20.         result = n * factorial(- 1);
  21.  
  22.     return result;
  23. }

constexpr 함수는 컴파일러에게 가능하다면, 상수시간에 컴파일해 달라고 요청하는 것이지만 상황에 따라 컴파일 타임에 미리 실행될 수도 있고, 그렇지 못하고 런타임에 실행될 수도 있다.
(마치 inline 키워드가 그러하듯이 말이다)

constexpr의 함수 인자들이 constexpr 규칙에 부합하지 못하는 경우엔 컴파일 타임에 실행되지 못하고 런타임에 실행된다.
런타임 실행 여부는 여러 가지 방식으로 검증해 볼 수 있다.
  • breakpoint 걸어서 중단되는지 확인
  • 아래 예제의 constN 같은 테스팅 템플릿 작성
  • 정수일 경우 배열의 dimension으로 작성

  1. // 템플릿 인자 N이 컴파일 타임 상수인지 테스트하기 위한 템플릿 구조체
  2. template<int n>
  3. struct constN
  4. {
  5.     constN() { std::cout << N << '\n'; }
  6. };

  7. constexpr int factorial(int n)
  8. {
  9.     return n <= 1 ? 1 : (* factorial(- 1));
  10. }
  11.  
  12. int main()
  13. {
  14.     // 4는 리터럴 타입이므로 상수 타임에 컴파일 성공
  15.     constN<factorial(4)> out1;
  16.  
  17.     // ab는 4의 값을 가지지만, 리터럴 타입이 아니므로 컴파일 에러 발생
  18.     // error C2975: 'N': 'constN'의 템플릿 인수가 잘못되었습니다. 컴파일 타임 상수 식이 필요합니다.
  19.     int ab = 4;
  20.     constN<factorial(ab)> out2;
  21.  
  22.     // 리터럴 타입이 아니므로, 이 함수는 런타임에 실행된다.
  23.     // 하지만 정상 동작한다.
  24.     int cd = factorial(ab);
  25.  
  26.     return 0;
  27. }

25라인에서 factorial 함수의 인자가 constexpr로 평가될 수 없기에, 함수이지만 런타임에 실행되는 것을 확인할 수 있다. 
이처럼 constexpr 함수는 인자가 constexpr에 부합한지에 따라, 컴파일 타임 또는 런타임에 실행되기에 범용적으로 사용되는 함수이고, 실행의 복잡도가 낮지 않다면, 가급적 constexpr 키워드를 붙이는 것도 괜찮은 습관이 되지 않을까 생각한다.

위의 예제에서는 함수가 어느 시점에 실행되는지 여부를 살펴보았지만, 무작정 constexpr 키워드를 붙일 수 있는 것도 아니다.
함수가 절대 상수표현식으로써 평가받지 못하는 문맥을 가지는 경우엔 컴파일 에러가 발생한다.

  1. constexpr int rand_short()
  2. {
  3.     // 절대 상수화가 될 수 없는 문맥
  4.     // error C3615: constexpr 함수 'randshort'의 결과가 상수 식이면 안 됩니다.
  5.     return rand() % 65535;
  6. }

컴파일 에러니까 함수 작성 후 바로 확인이 가능하기에 심각한 오류를 사전에 만나는 일은 없을 것이다.


3) 생성자 함수에서의 사용

LiteralType 클래스를 생성할 때 constexpr 생성자를 사용할 수 있다.
이 때의 제약은 다음과 같다.
  • 모든 생성자 함수의 매개변수들 역시 LiteralType들이어야 한다.
  • 어떤 클래스로부터 상속받지 않아야 한다

constexpr이 적용된 함수의 매개변수는 반드시 LiteralType이어야 한다고 했다.
이를 만족시키기 위해 constexpr 생성자 함수를 이용, LiteralType 클래스를 활용하는 예제를 살펴보도록 하자.

  1. // 아래 CountLowercast 함수의 인자로 사용하기 위한 LiteralType class
  2. class ConstString
  3. {
  4. private:
  5.     const char* p = null;
  6.     std::size_t sz = 0;
  7.  
  8. public:
  9.     template<std::size_t N>
  10.     constexpr ConstString(const char(&a)[N])
  11.     : p(a), sz(- 1)
  12.     {
  13.     }
  14.  
  15. public:
  16.     constexpr char operator[](std::size_t n) const
  17.     {
  18.         return n < sz ? p[n] : throw std::out_of_range("");
  19.     }
  20.  
  21. public:
  22.     constexpr std::size_t size() const { return sz; }
  23. };
  24.  
  25. // 소문자가 몇개인지 수를 세는 함수
  26. constexpr std::size_t CountLowercase(ConstString s, std::size_t n = 0, std::size_t c = 0)
  27. {
  28.     return n == s.size() ?
  29.                     c :
  30.                     s[n] >= 'a' && s[n] <= 'z' ?
  31.                         CountLowercase(s, n+1, c+1) :
  32.                         CountLowercase(s, n+1, c);
  33. }
  34.  
  35. // 컴파일타임 상수를 테스트해 보기 위한 템플릿
  36. template<int n>
  37. struct ConstN
  38. {
  39.     ConstN()
  40.     {
  41.         std::cout << n << '\n';
  42.     }
  43. };
  44.  
  45. int main()
  46. {
  47.     std::cout << "Number of lowercase letters in \"Hello, world!\" is ";
  48.  
  49.     // "Hello, world!"가 ConstString으로 암시적 형반환되어, CountLowercase 함수의 인자로 넘어감.
  50.     // CountLowercase는 컴파일 타임에 평가되었고, 그 결과를 가지고 ConstN 역시 컴파일 타임에 결정됨.
  51.     ConstN<CountLowercase("Hello, world!")> out;
  52.  
  53.     return 0;
  54. }


2. 템플릿 메타 프로그래밍 vs constexpr

constexpr은 컴파일 타임에 평가되기 때문에 템플릿 메타 프로그래밍(템플릿 함수가 인스턴스화될 때 값 계산)과 비교될 수 있다.
예를 들어, 똑같이 배열의 크기나 enum 열거형의 값과 같은 곳에서 상수로써 사용이 가능하다.

  1. // 템플릿 함수 방식의 Factorial
  2. template <int N>
  3. struct Template_Factorial
  4. {
  5.     enum { value = N * Template_Factorial<- 1>::value; }
  6. };
  7.  
  8. template <>
  9. struct Template_Factorial<0>
  10. {
  11.     enum { value = 1; }
  12. }
  13.  
  14. // constexpr 방식의 Factorial
  15. constexpr int Constexpr_Factorial(int n)
  16. {
  17.     return n <= 0 ? 1 : n  * Constexpr_Factorial(- 1);
  18. }
  19.  
  20. // constexpr 함수의 결과를 enum의 값으로 사용 가능
  21. enum FACTORIAL
  22. {
  23.     first  = Constexpr_Factorial(1),
  24.     second = Constexpr_Factorial(2),
  25.     third  = Constexpr_Factorial(3),
  26. };

위 예제에서 보듯이, 기존의 TMP에서 0과 같은 특수값을 사용하기 위해 템플릿 특수화를 했던 것에 비해, constexpr 함수는 훨씬 더 직관적인 방법을 제공할 수 있다.

위 예제에 피보나치까지 살짝 추가해, 조금 더 비교해 보면 기존 코드를 죄다 다시 작성하고 싶어질 것이다.

  1. template<unsigned n>
  2. struct Fibonacci
  3. {
  4.     static const unsigned value = Fibonacci<- 1>::value + Fibonacci<- 2>::value;
  5. };
  6.  
  7. template<>
  8. struct Fibonacci<0>
  9. {
  10.     static const unsigned value = 0;
  11. };
  12.  
  13. template<>
  14. struct Fibonacci<1>
  15. {
  16.     static const unsigned value = 1;
  17. };
  18.  
  19. int main()
  20. {
  21.     return Fibonacci<5>::value;  
  22. }
  23.  
  24. ///////////////////////////////////////////////////////////////////////////////////////////////

  25. constexpr unsigned fibonacci(const unsigned x)
  26. {
  27.     return x <= 1 ? 1 : fibonacci(- 1) + fibonacci(- 2);
  28. }
  29.  
  30. int main()
  31. {
  32.     return fibonacci(5);
  33. }


출처 : http://egloos.zum.com/sweeper/v/3147813

728x90

'Basic Programming > C++ 11' 카테고리의 다른 글

c++11 - atomic  (2) 2022.10.13
C++11 - Mordern C++ 프로그래머를 위한 C++ 11/14 핵심  (0) 2018.10.17
C++11 - final, override 키워드  (0) 2017.09.18
C++11 - std::thread  (0) 2016.12.02
C++11 - "default" and "delete" keyword  (0) 2016.11.29
728x90

쭉 읽어보니.. 너무 많은 듯 하여 요약 시킬 필요성을 느꼇다...

간단하게 요약만 하겠다. 본문(https://google.github.io/styleguide/cppguide.html#Nonstandard_Extensions) 참조할 것

 

모든 내용이 있는 것은 아니다... 잘 모르겠는 부분 또는 필요없어 보이는 부분은 넘어갔다.

 

 

- Header Guard를 할 것. (#pragma once, #ifdef...)

 

- Template, inline은 Header파일에 선언과 정의를 같이 넣을 것.

 

- Header파일에는 필요한 Header파일을 모두 include 할 것.

 

- Header Guard는 Project_Path_File_H 형식으로 만들어야 한다.

foo/src/bar/bar.z 파일의 경우 아래와 같이 작성한다.

#ifndef FOO_BAR_BAZ_H_ #define FOO_BAR_BAZ_H_  ...  #endif  // FOO_BAR_BAZ_H_

 

- forward declarations를 사용하지 말자.

#include <iostream>  int add(int x, int y); // forward declaration using function prototype  int main() {     using namespace std;     cout << "The sum of 3 and 4 is " << add(3, 4) << endl;     return 0; }
int add(int x, int y) {     return x + y; }

 

- inline function 은 함수의 길이가 10줄 이하일 때만 사용하자.

 

- include의 이름과 순서는 다음과 같이 한다.

공통 헤더, C 라이브러리, C++ 라이브러리, 다른 라이브러리의 Header, 프로젝트의 Header

 

- namespace는 몇몇 상황을 제외하고 사용하자. (using namespace 는 사용을 자제하자.)

 

- global 변수는 사용하지말 것, namespace 내부에 Nonmember 변수를 배치할 것, 단순히 static 함수를 그룹화하기 위해 클래스를 사용하지 말 것.

 

- 지역 변수의 경우 선언과 동시에 초기화를 할 것.

int i; i = f();      // Bad -- initialization separate from declaration. 
int j = g();  // Good -- declaration has initialization. 
std::vector<int> v; v.push_back(1);  // Prefer initializing using brace initialization. v.push_back(2); 
std::vector<int> v = {1, 2};  // Good -- v starts initialized.

 

- smart pointer(unique_ptr, share_ptr) 사용 금지.

 

- 생성자에서 virtual function 호출을 피하고 실패할 수 있는 초기화를 피할 것.

 

- 암묵적 형변환을 사용하지 말고 명시적 형변환을 사용하자.

 

- struct와 class를 분리해서 사용하고, struct는 데이터를 전달하는 passive object에만 사용할 것.

 

- class의 멤버 정의는 public, protected, private 순서로 정의해야 된다.

 

- 매개 변수를 이용한 출력보다는 return 값을 이용하자.

 

- 하나의 함수는 길이가 40줄이 넘지 않게 구현하자.

 

- RTTI 사용하지 말자.

 

- 사용해야할 때마다 const를 사용하고, c++11에서는 constexpr이 더 낫다.

 

- Preprocessor Macros를 Header에 선언하지말자. inline, enum, const 등을 더 사용하자.

 

- 정수는 0, 실수는 0.0, 포인터는 nullptr, 문자는 '\n'를 사용하자.

 

- sizeof(type)를 사용할때에는 type은 변수명을 사용하자.

Struct data; memset(&data, 0, sizeof(data)); 
memset(&data, 0, sizeof(Struct));

 

- auto를 남발하지말자.

 

- Lambda

  • Use lambda expressions where appropriate, with formatting as described below.
  • Prefer explicit captures if the lambda may escape the current scope. For example, instead of:
    {   Foo foo;   ...   executor->Schedule([&] { Frobnicate(foo); })   ... } // BAD! The fact that the lambda makes use of a reference to `foo` and // possibly `this` (if `Frobnicate` is a member function) may not be // apparent on a cursory inspection. If the lambda is invoked after // the function returns, that would be bad, because both `foo` // and the enclosing object could have been destroyed. 
    prefer to write:
    {   Foo foo;   ...   executor->Schedule([&foo] { Frobnicate(foo); })   ... } // BETTER - The compile will fail if `Frobnicate` is a member // function, and it's clearer that `foo` is dangerously captured by // reference.

 

- 복잡한 Template Metaprogramming은 피하자.

 

- Boost 라이브러리를 사용할 때에는 승인된 라이브러리만 사용하자.

 

- 적절한 경우에만 C++11을 사용해야하고, 프로젝트에서 C++11 기능을 사용하기 전에 다른 환경으로의 이식성도 고려해야한다.

 

- 일반 이름 지정 규칙

이름은 설명이 있어야한다. 약어를 피하자. wikipedia 목록에 있는 약어 정도는 괜찮다.

int price_count_reader;    // No abbreviation. int num_errors;            // "num" is a widespread convention. int num_dns_connections;   // Most people know what "DNS" stands for. int lstm_size;             // "LSTM" is a common machine learning abbreviation. 
int n;                     // Meaningless. int nerr;                  // Ambiguous abbreviation. int n_comp_conns;          // Ambiguous abbreviation. int wgc_connections;       // Only your group knows what this stands for. int pc_reader;             // Lots of things can be abbreviated "pc". int cstmr_id;              // Deletes internal letters. FooBarRequestInfo fbri;    // Not even a word.

 

- Type Names

Type names start with a capital letter and have a capital letter for each new word, with no underscores: MyExcitingClass, MyExcitingEnum.

The names of all types — classes, structs, type aliases, enums, and type template parameters — have the same naming convention. Type names should start with a capital letter and have a capital letter for each new word. No underscores. For example:

// classes and structs class UrlTable { ... class UrlTableTester { ... struct UrlTableProperties { ...  // typedefs typedef hash_map<UrlTableProperties *, string> PropertiesMap;  // using aliases using PropertiesMap = hash_map<UrlTableProperties *, string>;  // enums enum UrlTableErrors { ...

 

- Variable Names

변수의 이름 (함수, 매개 변수 포함) 및 데이터 멤버는 모두 소문자로 시작하며 다너 사이에 밑줄이 있을 수 있다. 클래스의 데이터 멤버 변수에는 마지막에 밑줄을 넣는다.

Common Variable names

For example:

string table_name;  // OK - uses underscore. string tablename;   // OK - all lowercase. 
string tableName;   // Bad - mixed case.

 

클래스

Data members of classes, both static and non-static, are named like ordinary nonmember variables, but with a trailing underscore.

class TableInfo {   ...  private:   string table_name_;  // OK - underscore at end.   string tablename_;   // OK.   static Pool<TableInfo>* pool_;  // OK. };

 

구조체

Data members of structs, both static and non-static, are named like ordinary nonmember variables. They do not have the trailing underscores that data members in classes have.

struct UrlTableProperties {   string name;   int num_entries;   static Pool<UrlTableProperties>* pool; }; 

See Structs vs. Classes for a discussion of when to use a struct versus a class.

 

Const

Variables declared constexpr or const, and whose value is fixed for the duration of the program, are named with a leading "k" followed by mixed case. Underscores can be used as separators in the rare cases where capitalization cannot be used for separation. For example:

const int kDaysInAWeek = 7; const int kAndroid8_0_0 = 24;  // Android 8.0.0 

All such variables with static storage duration (i.e. statics and globals, see Storage Duration for details) should be named this way. This convention is optional for variables of other storage classes, e.g. automatic variables, otherwise the usual variable naming rules apply.

 

함수 이름

Regular functions have mixed case; accessors and mutators may be named like variables.

Ordinarily, functions should start with a capital letter and have a capital letter for each new word.

AddTableEntry() DeleteUrl() OpenFileOrDie() 

(The same naming rule applies to class- and namespace-scope constants that are exposed as part of an API and that are intended to look like functions, because the fact that they're objects rather than functions is an unimportant implementation detail.)

Accessors and mutators (get and set functions) may be named like variables. These often correspond to actual member variables, but this is not required. For example, int count() and void set_count(int count).

 

네임스페이스 이름은 모두 소문자로 한다.

 

Enumerators

Enumerators (for both scoped and unscoped enums) should be named either like constants or like macros: either kEnumName or ENUM_NAME.
Preferably, the individual enumerators should be named like constants. However, it is also acceptable to name them like macros. The enumeration name, UrlTableErrors (and AlternateUrlTableErrors), is a type, and therefore mixed case.
enum UrlTableErrors {  kOK = 0,  kErrorOutOfMemory,  kErrorMalformedInput,};enum AlternateUrlTableErrors {  OK = 0,  OUT_OF_MEMORY = 1,  MALFORMED_INPUT = 2,};

 

매크로 이름

일반 적으로는 매크로는 사용하지 않아야한다. 하지만 사용해야 한다면 모든 글자는 대문자와 밑줄로 지정해야 한다.

#define ROUND(x) ... #define PI_ROUNDED 3.0

 

- 주석 // 또는 /* */ 중에서 //을 더 많이 사용하도록 하자.

 

- 코드 한줄당 80자를 초과하지 말자.

 

- ASCII 보다는 UTF-8을 사용하자.

 

- Tab보다는 Spacebar를 사용하자.

 

- 조건부

Prefer no spaces inside parentheses. The if and else keywords belong on separate lines.

There are two acceptable formats for a basic conditional statement. One includes spaces between the parentheses and the condition, and one does not.

The most common form is without spaces. Either is fine, but be consistent. If you are modifying a file, use the format that is already present. If you are writing new code, use the format that the other files in that directory or project use. If in doubt and you have no personal preference, do not add the spaces.

if (condition) {  // no spaces inside parentheses   ...  // 2 space indent. } else if (...) {  // The else goes on the same line as the closing brace.   ... } else {   ... } 

If you prefer you may add spaces inside the parentheses:

if ( condition ) {  // spaces inside parentheses - rare   ...  // 2 space indent. } else {  // The else goes on the same line as the closing brace.   ... } 

Note that in all cases you must have a space between the if and the open parenthesis. You must also have a space between the close parenthesis and the curly brace, if you're using one.

if(condition) {   // Bad - space missing after IF. if (condition){   // Bad - space missing before {. if(condition){    // Doubly bad. 
if (condition) {  // Good - proper space after IF and before {. 

Short conditional statements may be written on one line if this enhances readability. You may use this only when the line is brief and the statement does not use the else clause.

if (x == kFoo) return new Foo(); if (x == kBar) return new Bar(); 

This is not allowed when the if statement has an else:

// Not allowed - IF statement on one line when there is an ELSE clause if (x) DoThis(); else DoThat(); 

In general, curly braces are not required for single-line statements, but they are allowed if you like them; conditional or loop statements with complex conditions or statements may be more readable with curly braces. Some projects require that an if must always have an accompanying brace.

if (condition)   DoSomething();  // 2 space indent.  if (condition) {   DoSomething();  // 2 space indent. } 

However, if one part of an if-else statement uses curly braces, the other part must too:

// Not allowed - curly on IF but not ELSE if (condition) {   foo; } else   bar;  // Not allowed - curly on ELSE but not IF if (condition)   foo; else {   bar; } 
// Curly braces around both IF and ELSE required because // one of the clauses used braces. if (condition) {   foo; } else {   bar; }

 

728x90
728x90
728x90
728x90

OpenGL 은 기본적으로 Math Class가 없다. (DirectX는 있는데...)


OpenGL 자체가 원래는 시뮬레이션을 위해 만들어진 라이브러리이기 때문에, 이것을 사용하는 개발자들은 기본적으로 엄청

난 수학적 능력을 가졌다고 가정하고 안만들었다는데... 맞나모르겠네 ㅋ


그래서 Math Class를 사용하기 위해 GLM(OpenGL Mathematics)를 설치해야 한다.


1. GLM 다운로드하기

https://glm.g-truc.net/0.9.9/index.html 에 가서 Download를 눌러서 받는다.


2. unzip 압축풀기


3. glm 폴더 복사

압축을 풀면 다음과 같은 폴더들이 있는데, 이 중에서 glm 폴더를 "복사"한다.

glm 폴더를 원하는 곳에 "붙여넣기" 한다.


4. 이제 Visual Studio에서 폴더를 등록하고 사용하자.


출처 : http://justdoitproject.tistory.com/16

728x90

'Visualization Programming > OpenGL' 카테고리의 다른 글

OpenGL - Proland  (0) 2018.11.20
OpenGL - 설치하기  (0) 2018.08.10
728x90

OpenGL을 사용하기 위해서... 설치하려고 사이트들을 다 뒤져보니... 


GLUT를 모두들 설치하라고한다. 하지만 GLUT는 Windows에서는 64bit를 지원하지 않는 듯하다 !!


그래서 GLUT 설치는 하지 않고, Windows 10을 설치할 때 원래 있는 OpenGL 을 이용하기로 마음 먹었다.


현재 버전을 확인해보니 4.5.0 버전이다. 뒤에 버전이 어떻게 될지 모르겠지만 이렇게 공부해야지... ㅎㅎ


공부는 어떻게하지 ㅎㅎ...

728x90

'Visualization Programming > OpenGL' 카테고리의 다른 글

OpenGL - Proland  (0) 2018.11.20
OpenGL - GLM 설치하기.  (0) 2018.08.10

+ Recent posts