第一段階として、まずは簡単な3Dテストプログラムを与え、それに必要な知識である一からC++の必要最低限機能から、OpenGLの基本の解説を行ない、理解を深める。
この構成により、テストプログラムの改造を行ないながら学習を進めることが出来るためである。
第二段階として、ファイル入出力と、第一段階で決め打ちハードコーディングしていた部分を、汎用的なコードに置き換える。
第三段階として、汎用的なシーングラフを構成するための基本を学ぶ。
この本は、3Dに興味はあるが、知識が付いて行かない人達のための参考書である。
この本をきっかけに、3Dプログラミング人口が増え、メガデモ世界が発展すれば良いと思う。
秘訣として言える事は、空想力が全てである。心の目を持って空想出来る事が、プログラム作成に必要なスキルである。
※その他の魔術は、これらで得た知識を応用するなどして独自に開発されたし。
2進数 | 16進数(10進数) |
---|---|
0 1 10 11 100 101 110 111 1000 1001 1010 1011 1100 1101 1110 1111 . . . 11111111 | 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA(10) 0xB(11) 0xC(12) 0xD(13) 0xE(14) 0xF(15) . . . 0xFF(255) |
| 0 1 2 3 4 5 6 7 8 9 a b c d e f ---+------------------------------------------------ 0 | ^@ ^A ^B ^C ^D ^E ^F ^G ^H ^I ^J ^K ^L ^M ^N ^O 1 | ^P ^Q ^R ^S ^T ^U ^V ^W ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ 2 | ! " # $ % & ' ( ) * + , - . / 3 | 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 4 | @ A B C D E F G H I J K L M N O 5 | P Q R S T U V W X Y Z [ \ ] ^ _ 6 | ` a b c d e f g h i j k l m n o 7 | p q r s t u v w x y z { | } ~ ^? (以下省略)初心者に説明しておいたほうが良い文字コードを下記に示す。
ちなみに、コンパイラ等のソフトウェア取得のため、インターネット接続環境は必須である。
このダウンロードしたファイルを実行し、インストールする。
デスクトップにMSYS2 MinGW 32-bitというアイコンが出来るので実行します。
するとMSYS2のコマンドプロンプト(コマンド入力待ち文字)が表示されるので、下記のコマンドを入力して、必要なコンパイラやコマンド、およびライブラリをインストールします。
pacmanのコマンドを入力するとインストールするかどうか聞いてくるので、そのままReturn(Enter)キーを押して(Yesと答えて)やってください。
入力するコマンド | 説明 |
---|---|
pacman -S mingw-w64-i686-gcc | コンパイラ。 |
pacman -S mingw-w64-i686-make | 自動makeコマンド。(GNU make) |
pacman -S mingw-w64-i686-freeglut | OpenGL utility toolkitライブラリ。 |
pacman -S unzip | zipファイルを展開するコマンド。 |
pacman -S zip | zipファイルを作成するコマンド。 |
pacman -S tar | tarファイルを展開するコマンド。 |
pacman -S patch | ファイルにパッチを当てるコマンド。 |
pacman -S diffutils | configureに必要なcmpコマンドが含まれている。 |
pacman -S texinfo | configureに必要なmakeinfoコマンドが含まれている。 |
pacman -S tcsh | コマンド入力を受け付けるコマンド、シェルという。 |
入力するコマンド(例) | 説明 |
---|---|
cd /c/msys32 | cドライブにmsys32をインストールした場合。 |
unzip ../Users/alumina/Downloads/mingw32-gdb-7.12.1.zip | aluminaの部分は自分のユーザー名等に置き換えること。 |
diff -u gdb-7.12.1.orig/configure gdb-7.12.1/configure --- gdb-7.12.1.orig/configure 2017-01-21 22:48:42.000000000 +0900 +++ gdb-7.12.1/configure 2017-11-07 09:44:20.646416700 +0900 @@ -5902,7 +5902,7 @@ # if supported. But if the user explicitly specified the libraries to use, # trust that they are doing what they want. if test "$stage1_libs" = "" -a "$have_static_libs" = yes; then - stage1_ldflags="-static-libstdc++ -static-libgcc" + stage1_ldflags="" fi fi @@ -5938,7 +5938,7 @@ # statically. But if the user explicitly specified the libraries to # use, trust that they are doing what they want. if test "$poststage1_libs" = ""; then - poststage1_ldflags="-static-libstdc++ -static-libgcc" + poststage1_ldflags="" fi fi |
URL: http://cha.la.coocan.jp/doc/NTEmacs.html
--- emacs/share/emacs/25.3/etc/charsets/JISX0208.map.orig 2017-04-15 00:35:06.000000000 +0900 +++ emacs/share/emacs/25.3/etc/charsets/JISX0208.map 2017-10-21 12:17:57.839691200 +0900 @@ -31,7 +31,7 @@ 0x213e 0x2010 0x213f 0xFF0F 0x2140 0xFF3C -0x2141 0x301C +0x2141 0xFF5E 0x2142 0x2016 0x2143 0xFF5C 0x2144 0x2026 |
入力するコマンド | 説明 |
---|---|
cd (emacs-25.3-simple_ime-no_symbolのディレクトリ) | cdコマンドでカレントディレクトリを移動します。 |
patch JISX0208.map.diff | パッチを当てます。 |
set LC_TIME=C set TZ=JST-9 set LANG=ja_JP.SJIS set HOME=c:\cygwin\home\alumina emacs-25.3.3.exe -geometry 165x53+300+0 %* |
(setq-default message-log-max 10000) (cond ((>= emacs-major-version 25) (setq load-path (append (list (expand-file-name "~/.el/emacs25") (expand-file-name "~/.el/emacs21") (expand-file-name "~/.el/emacs20") (expand-file-name "~/.el") ) load-path )) ) ) (load "cursormove") (load "cc-mode") (load "hexl") (load "jka-compr") (load "sh-script") (load "perl-mode") (load "make-mode") (load "html-helper-mode") ;; (require 'web-mode) (load "misckey") (cond ((>= emacs-major-version 24) ; New! emacs24 (set-language-environment "Japanese") (blink-cursor-mode nil) (setq scalable-fonts-allowed nil) (cond ((eq window-system 'x) (setq-default yc-rK-trans-key [henkan]) ) ) (cond ((eq system-type 'windows-nt) ) (t (setq yc-server-host "canna") (load "ycset") (setq default-input-method "japanese-yc") (load "cannaset") ) ) (set-terminal-coding-system 'shift_jis-unix) ;euc-japan-1990-unix. (setq-default default-process-coding-system '(undecided . sjis)) ;(iso-2022-jp . iso-2022-jp) (setq-default default-file-name-coding-system 'shift_jis-unix) (set-keyboard-coding-system 'shift_jis) ) ) ;;; running-mode specific environment.(face, color) (cond ((and (>= emacs-major-version 25) (eq system-type 'windows-nt)) (menu-bar-mode 0) (tool-bar-mode 0) (toggle-scroll-bar 0) ; スクロールバーを消す. (load "dired") (load "win32cust") ;;(load "w32font") (load "faceset") ) ((>= emacs-major-version 25) (menu-bar-mode 0) (tool-bar-mode 0) (toggle-scroll-bar 0) ; スクロールバーを消す. (load "dired") (load "faceset") ) ((eq window-system 'x) (menu-bar-mode 0) (toggle-scroll-bar 0) ; スクロールバーを消す. (load "dired") (load "faceset") ) (t ;(and (null window-system) ; (= emacs-major-version 20)) ;(null window-system) (menu-bar-mode 0) ) ) (cond ((featurep 'meadow) ; (eq window-system 'w32) ) (t (load "setmodeline") ) ) (cond ((featurep 'xemacs) ) (t ;; ~/.saves-*を作らないようにする. (setq auto-save-list-file-prefix nil) ) ) (setq comint-scroll-show-maximum-output t) (setq-default find-file-wildcards t) (setq search-highlight t query-replace-highlight t) ;;(setq-default case-fold-search nil) ; 大文字/小文字区別 is nil (setq-default comment-multi-line t) ;;(setq-default comment-padding 0) ; for comment-region (cond ((<= emacs-major-version 23) (resize-minibuffer-mode 1) ) ) (setq-default resize-minibuffer-mode t) (setq-default line-number-mode t) (setq-default column-number-mode t) (setq-default tab-width 8) (setq-default visible-bell t) ; 音を静かに. (setq-default scroll-step 1) ; スクロールを1行毎に行う. (setq display-time-24hr-format t) ; 24時間表示. (display-time) (setq-default truncate-partial-width-windows nil) ; 長い行の折り返しON. (setq-default truncate-lines nil) ; (全画面時の)折り返し(OFF == t). ;;(next-screen-context-lines 2) ; M-v/C-M-vで、残す行数. (setq-default split-window-keep-point nil) ; C-x 2時、表示位置を維持する. ;;(setq-default no-redraw-on-recenter t) ; C-lで、中央以外のまま. (setq-default next-line-add-newlines nil) (setq-default view-read-only t) (setq-default font-lock-maximum-size 1048576) ;; programming environment. (setq-default c-default-style "alumina"); (setq-default c-indentation-style nil) ; "alumina" (setq-default c-style-variables-are-local-p t) (setq-default vc-initial-comment t) (setq-default compile-command "make -k ") (setq-default diff-switches "-u") ; "diff -u". (setq-default grep-command "grep -nie ") (setq-default manual-program "man") (setq-default woman-use-own-frame nil) (eval-after-load "sh-script" '(put 'sh-mode 'mode-class nil) ) (setenv "XMODIFIERS" nil) (add-hook 'dired-mode-hook (lambda () (make-local-variable 'process-environment) (setenv "LC_TIME" "C") ;; (setenv "LANG" "C") )) (add-hook 'Man-mode-hook (lambda() (make-local-variable 'process-environment) (setenv "LANG" "ja_JP.eucJP") (setenv "JLESSCHARSET" "japanese-ujis") (setenv "LESSCHARSET" nil) (make-local-variable 'default-process-coding-system) (setq default-process-coding-system '(euc-jp-unix . euc-jp-unix)) ;; (make-local-variable 'default-buffer-file-coding-system) ;; (setq default-buffer-file-coding-system 'euc-jp-unix) ;; (make-local-variable 'buffer-file-coding-system) ;; (setq buffer-file-coding-system 'euc-jp-unix) (make-local-variable 'coding-system-for-read) (setq coding-system-for-read 'euc-jp-unix) )) (load "srcalumina") ;;(load "srcbsd") ;;(load "srclinux") (load "sql") (setq html-helper-basic-offset 4) (setq html-helper-item-continue-indent 0) (setq html-helper-search-limit 32768) ;;;; major mode specific environment. (setq comment-padding 1) ;; file coding system. (load "filecode.el") (add-hook 'sh-mode-hook (function (lambda () (setq comment-start "#") (to-euc-jp-unix)))) (add-hook 'text-mode-hook (function (lambda () (to-sjis-dos)))) ;; (auto-fill-mode t)))) (add-hook 'sql-mode-hook (function (lambda () (sql-highlight-postgres-keywords t) (to-sjis-dos)))) (add-hook 'c-mode-common-hook (lambda() ; (to-euc-jp-unix) ;; (c-set-style c-site-default-style) (setq c-comment-only-line-offset 1) ;; (to-sjis-dos);; メモ帳で編集可能ソースにしたい場合はこちらを有効に. (to-sjis-unix) )) (add-hook 'c++-mode-hook (lambda() (setq comment-start "//") ;; (to-sjis-dos);; メモ帳で編集可能ソースにしたい場合はこちらを有効に. (to-sjis-unix) )) (add-hook 'html-helper-mode-hook (lambda() (setq tab-width 4) ;; (to-sjis-unix) (require 'html-region) (auto-fill-mode 0) )) ;; (add-hook 'web-mode-hook ;; (lambda() ;; (setq web-mode-markup-indent-offset 0) ;; (to-sjis-unix) ;; )) (add-hook 'makefile-mode-hook (lambda() (to-euc-jp-unix) )) ;; (require 'eldoc) (add-hook 'lisp-interaction-mode 'turn-on-eldoc-mode) ;; (add-hook 'emacs-lisp-mode-hook ) (add-hook 'emacs-lisp-mode-hook (lambda () (turn-on-eldoc-mode) (outline-minor-mode 1) )) (cond ((>= emacs-major-version 20) (setq file-coding-system-alist (append '(;; extension read . write ("\\.xml\\'" undecided . utf-8) ("\\.lst\\'" sjis-unix . undecided) ("\\.txt\\'" undecided . sjis-dos) ("\\.TXT\\'" undecided . sjis-dos) ("\\.hnf\\'" undecided . sjis-dos) ("\\.htm[l]\\'" undecided . sjis-dos) ("\\.sql\\'" undecided . euc-jp-dos) ("\\.sh\\'" undecided . euc-jp-unix) ("\\.pl\\'" undecided . sjis-unix) ("\\.php[3]\\'" undecided . euc-jp-unix) ; ("\\.vmg\\'" iso-2022-jp-dos . no-conversion) ("\\.emacs\\'" iso-2022-jp-unix . no-conversion) ("\\.wav\\'" no-conversion . no-conversion) ("\\.bmp\\'" no-conversion . no-conversion) ("\\.tga\\'" no-conversion . no-conversion) ("/\\.navi2ch/.*\\.dat\\'" sjis-dos . no-conversion) ) file-coding-system-alist)) (setq file-coding-system-alist (append '(;; extension read . write ("\\.c\\'" undecided . sjis-unix) ("\\.h\\'" undecided . sjis-unix) ("\\.cc\\'" undecided . sjis-unix) ("\\.cpp\\'" undecided . sjis-unix) ("\\.tcc\\'" undecided . sjis-unix) ("\\.icc\\'" undecided . sjis-unix) ) file-coding-system-alist)) )) (setq auto-mode-alist (append '( ("\\.\\(cc\\|cpp\\|hpp\\|tcc\\|icc\\)$" . alumina-c++-mode) ("\\.h$" . alumina-c++-mode) ("\\.c$" . alumina-c-mode) ("\\.[Tt][Ee]?[Xx][Tt]\\'" . sjis-text-mode) ("\\.[Bb][Aa][Tt]\\'" . sjis-text-mode) ("\\.canna$" . emacs-lisp-mode) ("\\.[Pp][Ll]$" . perl-mode) ("\\.html?\\'" . html-helper-mode) ;; ("\\.html?\\'" . web-mode) ;; ("\\.phtml\\'" . web-mode) ;; ("\\.tpl|\\.php\\'" . web-mode) ;; ("\\.[agj]sp\\'" . web-mode) ;; ("\\.as[cp]x\\'" . web-mode) ;; ("\\.erb\\'" . web-mode) ;; ("\\.mustache\\'" . web-mode) ;; ("\\.djhtml\\'" . web-mode) ("\\.mk$" . makefile-mode) ("[mM]akefile.*$" . makefile-mode) ("[iI]makefile.*$" . makefile-mode) ("\\.wav\\'" . hexl-mode) ("\\.bmp\\'" . hexl-mode) ("\\.tga\\'" . hexl-mode) ) auto-mode-alist)) (setq-default tags-table-list '( "/usr/include" "/sys" "/usr/local/include" )) (put 'narrow-to-region 'disabled nil) (put 'upcase-region 'disabled nil) (put 'downcase-region 'disabled nil) |
;; \C-nで,fileの最後に改行文字を追加しない. (setq next-line-add-newlines nil) ;; viの '%'のように、対応する括弧に移動. (defun match-paren (arg) "Go to the matching parenthesis if on parenthesis otherwise insert %." (interactive "p") (cond ((looking-at "[([{<]") (forward-sexp 1) (backward-char)) ((looking-at "[])}>]") (forward-char) (backward-sexp 1)) (t (self-insert-command (or arg 1))))) (global-set-key "%" 'match-paren) ;; バッファ端での警告を出さない上下移動関数. (defun previous-line (arg) (interactive "p") (condition-case nil (line-move (- arg)) (beginning-of-buffer))) (defun next-line (arg) (interactive "p") (condition-case nil (line-move (+ arg)) (end-of-buffer))) ;; 直前の windowへ移動. (defun other-window-backward (&optional n) "Select the Nth previous window." (interactive "P") (other-window (- (prefix-numeric-value n)))) ;; カーソル行の手前に、新たな行を追加。(viの, "O"キー風) (defun open-line2 () "Insert a newline and indent." (interactive "*") (beginning-of-line) (newline) (previous-line 1) (indent-according-to-mode)) ;; カーソル行の直後に新たな行を追加し,インデントを行う. (defun open-line3 () "Append a newline and indent." (interactive "*") (end-of-line) (newline) (indent-according-to-mode)) ;; マウスホイール用スクロール関数. ;; ついでにバッファ端での警告を出さない. (defvar mouse-scroll-lines 3) (defun mouse-scroll-down () "mouse wheel scroll function." (interactive "") (condition-case nil (scroll-down mouse-scroll-lines) (beginning-of-buffer))) (defun mouse-scroll-up () "mouse wheel scroll function." (interactive "") (condition-case nil (scroll-up mouse-scroll-lines) (end-of-buffer))) |
(cond ((>= emacs-major-version 25) ; x window system emacs25. (put 'backspace 'ascii-character 8) ; backspaceコードを^Hに. (global-set-key "\C-h" 'backward-delete-char) (global-set-key [?\d] 'backward-delete-char) (global-set-key "\C-\\" 'undo) (global-set-key [mouse-4] 'mouse-scroll-down) (global-set-key [mouse-5] 'mouse-scroll-up) (define-key emacs-lisp-mode-map [backspace] 'backward-delete-char) (define-key lisp-mode-map [backspace] 'backward-delete-char) (global-set-key "\C-x\C-b" 'electric-buffer-list) )) (define-key c-mode-map "\C-\M-h" 'backward-kill-word) (define-key c++-mode-map "\C-\M-h" 'backward-kill-word) (define-key sh-mode-map "\C-c\C-c" 'comment-region) (define-key perl-mode-map "\C-c\C-c" 'comment-region) (define-key perl-mode-map "\C-\M-h" 'backward-kill-word) (define-key isearch-mode-map "\C-h" 'isearch-delete-char) (define-key isearch-mode-map "\C-\\" 'undo) (cond ((>= emacs-major-version 21) (define-key emacs-lisp-mode-map "\C-c\C-c" 'comment-region) (define-key lisp-mode-map "\C-c\C-c" 'comment-region) ) ) (define-key makefile-mode-map "\C-c\C-c" 'comment-region) (define-key html-helper-mode-map "\C-c\C-c" 'comment-region) ;; (define-key web-mode-map "\C-c\C-c" 'comment-region) (define-key hexl-mode-map "\C-x\C-p" 'other-window-backward) (global-set-key [insert] 'overwrite-mode) ;defaultでtoggleなのだ. (global-set-key [delete] 'delete-char) ;delete (global-set-key [insertchar] 'overwrite-mode) ;defaultでtoggleなのだ. (global-set-key [deletechar] 'delete-char) ;delete (global-set-key [home] 'other-window) (cond ((not (featurep 'xemacs)) (global-set-key [\S-home] 'other-window-backward) ) ) (global-set-key "\M-?" 'help-command) (global-set-key [help] 'help-for-help) (global-set-key "\M-\C-h" 'backward-kill-word) (global-set-key "\C-x_" 'shrink-window) (cond ((featurep 'xemacs) ) (t (define-key function-key-map [S-return] [?\015]) ;Return (define-key function-key-map [C-return] [?\015]) ;Return (define-key function-key-map [M-return] [?\015]) ;Return ) ) (global-set-key [end] 'end-of-buffer) (cond ((featurep 'xemacs) ) (t (global-set-key [\S-end] 'beginning-of-buffer) ) ) (global-set-key "\C-x\C-n" 'other-window) (global-set-key "\C-x\C-p" 'other-window-backward) (global-set-key "\M-o" 'open-line2) ;カーソル行に空行追加. (global-set-key "\M-m" 'open-line3) (global-set-key "\M-g" 'goto-line) |
(when (locate-library "w32-ime") (progn (w32-ime-initialize) (setq default-input-method "W32-IME") (setq-default w32-ime-mode-line-state-indicator "[--]") (setq w32-ime-mode-line-state-indicator-list '("-" "[あ]" "[--]")) ;; (setq w32-ime-mode-line-state-indicator-list '("[--]" "[あ]" "[--]")) )) (global-set-key "\C-z" 'undo) (set-fontset-font nil 'japanese-jisx0208 (font-spec :family "Ricty Diminished")) (setq face-font-rescale-alist '(("Ricty Diminished" . 1.08))) (set-face-attribute 'default nil :family "Ricty Diminished" :height 130) (setq shell-file-name "c:/msys32/usr/bin/tcsh.exe") (setq explicit-shell-file-name "c:/msys32/usr/bin/tcsh.exe") |
(global-font-lock-mode t) (font-lock-mode) (cond ((<= emacs-major-version 21) (setq-default c++-font-lock-extra-types (append '("\\sw+_s" "\\sw+_e" "\\sw+_f" "\\sw+_a" "linear" "links" "bin") c++-font-lock-extra-types)) ) ) (setq-default font-lock-maximum-decoration t) (cond ((>= emacs-major-version 25) (set-foreground-color "gray90") (set-background-color "black") (set-border-color "blue") (set-face-background 'mode-line "blue") (set-face-foreground 'mode-line "skyblue") ) ) (make-face 'calendar-today-face) (make-face 'holiday-face) (make-face 'diary-face) (set-face-foreground 'calendar-today-face "skyblue") (set-face-foreground 'holiday-face "pink") (set-face-background 'holiday-face "black") (set-face-foreground 'diary-face "lightgreen") (set-face-background 'diary-face "black") (set-face-foreground 'font-lock-comment-face "moccasin") (set-face-foreground 'font-lock-builtin-face "lightskyblue2") (set-face-foreground 'font-lock-function-name-face "SteelBlue1") ;(set-face-foreground 'font-lock-variable-name-face "lightgreen") (set-face-foreground 'font-lock-keyword-face "lightskyblue2") ;(set-face-foreground 'font-lock-type-face "lightgreen") (set-face-foreground 'font-lock-string-face "darkorange") (set-face-foreground 'font-lock-warning-face "firebrick") (setq dired-font-lock-keywords (append (list ; (list dired-re-exe '(0 font-lock-variable-name-face)) (list dired-re-exe '(".+" (dired-move-to-filename) nil (0 font-lock-type-face))) ) dired-font-lock-keywords )) ;; manual face. (make-face 'man-overstrike-face) (set-face-foreground 'man-overstrike-face "white") (set-face-bold-p 'man-overstrike-face t) (setq Man-overstrike-face 'man-overstrike-face) (make-face 'man-underline-face) (set-face-foreground 'man-underline-face "yellow") (set-face-underline-p 'man-underline-face t) (setq Man-underline-face 'man-underline-face) (setq-default mew-highlight-body-color-comment "darkgray") (setq-default mew-highlight-body-color-quote "lightgreen") (setq-default mew-highlight-header-color-from "aquamarine") (setq-default mew-highlight-header-color-important "moccasin") (setq-default mew-highlight-header-color-key "lightgreen") (setq-default mew-highlight-header-color-marginal "darkgray") (setq-default mew-highlight-header-color-private "moccasin") (setq-default mew-highlight-header-color-subject "white") (setq-default mew-highlight-header-color-to "skyblue") (setq-default mew-highlight-mark-color-delete "red") (setq-default mew-highlight-mark-color-multi "magenta") (setq-default mew-highlight-mark-color-refile "lightgreen") (setq-default mew-highlight-mark-color-review "cyan") (make-face 'yc-current-face) (set-face-foreground 'yc-current-face "black") (set-face-background 'yc-current-face "skyblue") (make-face 'yc-fence-face) (set-face-foreground 'yc-fence-face "skyblue") (set-face-background 'yc-fence-face "black") ;; (make-face 'web-mode-html-tag-face) ;; (set-face-foreground 'web-mode-html-tag-face "SkyBlue") ;; (set-face-bold 'web-mode-html-tag-face t) |
(setq-default display-time-string-forms '((if (and (not display-time-format) display-time-day-and-date) (format-time-string "%a %b %e " now) "") (format-time-string (or display-time-format (if display-time-24hr-format "%H:%M" "%-I:%M%p")) now) ; '((if display-time-day-and-date ; (format "%s %s %s " dayname monthname day) ; "") ; (format "%s:%s%s" ; (if display-time-24hr-format 24-hours 12-hours) ; minutes ; (if display-time-24hr-format "" am-pm)) ;; この、load表示を消したかった!!! ;; load (if mail " Mail" ""))) |
;; filecode.el - set the file coding system. (defun to-euc-jp-unix () "To change the specified file coding system, if otherwise." (cond ((eq buffer-file-coding-system 'undecided)) ; ((eq buffer-file-coding-system 'undecided-dos)) ((eq buffer-file-coding-system 'undecided-unix)) ((eq buffer-file-coding-system 'japanese-iso-8bit-unix)) (t (set-buffer-file-coding-system 'euc-jp-unix))) ) (defun to-sjis-unix () "To change the specified file coding system, if otherwise." (cond ((eq buffer-file-coding-system 'undecided)) ((eq buffer-file-coding-system 'undecided-unix)) ((eq buffer-file-coding-system 'japanese-shift-jis-unix)) (t (set-buffer-file-coding-system 'sjis-unix) )) ) (defun to-sjis-dos () "To change the specified file coding system, if otherwise." (cond ((eq buffer-file-coding-system 'undecided)) ((eq buffer-file-coding-system 'undecided-dos)) ((eq buffer-file-coding-system 'japanese-shift-jis-dos)) (t (set-buffer-file-coding-system 'sjis-dos) )) ) (defun to-iso2022jp-dos () "To change the specified file coding system, if otherwise." (cond ((eq buffer-file-coding-system 'undecided)) ((eq buffer-file-coding-system 'undecided-dos)) ((eq buffer-file-coding-system 'iso-2022-jp-dos)) (t (set-buffer-file-coding-system 'iso-2022-jp-dos) )) ) (defun sjis-text-mode () "" (interactive) (to-sjis-dos) (text-mode) ) (defun iso2022jp-text-mode () "" (interactive) (to-iso2022jp-dos) (text-mode) ) |
(or (assoc "alumina" c-style-alist) (progn (c-add-style "alumina" '( (tab-width . 4) (c-basic-offset . 4) (c-offsets-alist . ((substatement-open . 0) (statement-cont . 8) ;; (substatement . 8) (arglist-intro . 8) ;; (arglist-cont . 8) )) ; "bsd" ) nil) )) (defun alumina-c-mode () "C mode with adjusted defaults for use with the alumina's source code." (interactive) ; (setq c-site-default-style "alumina") (c-mode) (c-set-style "alumina") ; (setq c-basic-offset 4) ; (setq tab-width 4) ) (defun alumina-c++-mode () "C++ mode with adjusted defaults for use with the alumina's source code." (interactive) ; (setq c-site-default-style "alumina") (c++-mode) (c-set-style "alumina") ; (setq c-basic-offset 4) ; (setq tab-width 4) ) |
おまけその1:unix環境で利用する場合、日本語変換にcannaを使用することが多いと思いますが、その設定です。
(cond ((or (and (= emacs-major-version 20) (>= emacs-minor-version 7)) (and (boundp 'CANNA) ; canna. (>= emacs-major-version 21)) ) (require 'canna) (load-library "canna") (setq canna-use-color '("skyblue" "black/skyblue" "black/springgreen")) (setq canna-do-keybind-for-functionkeys nil) ;; (setq canna-underline t) ; 変換文節にアンダーラインを引く. (canna) (setq canna-save-undo-text-predicate ;アンドゥバッファへ入れる条件. '(lambda (s) (> (length (car s)) 2)) ) (cond ((and (>= emacs-major-version 21) (null window-system)) (define-key canna-mode-map [backspace] [?\C-h]) (define-key canna-mode-map [delete] [?\C-d]) (define-key canna-mode-map [DEL] [?\C-h]) (define-key canna-minibuffer-mode-map [backspace] [?\C-h]) (define-key canna-minibuffer-mode-map [delete] [?\C-d]) (define-key canna-minibuffer-mode-map [DEL] [?\C-h]) ) ((eq window-system 'x) (define-key canna-mode-map [backspace] [?\C-h]) (define-key canna-mode-map [delete] [?\C-d]) (define-key canna-minibuffer-mode-map [backspace] [?\C-h]) (define-key canna-minibuffer-mode-map [delete] [?\C-d]) ) ((null window-system) (define-key canna-mode-map [?\C-?] [?\C-h]) (define-key canna-minibuffer-mode-map [?\C-?] [?\C-h]) (define-key canna-mode-map [backspace] [?\C-h]) (define-key canna-mode-map [delete] [?\C-d]) (define-key canna-minibuffer-mode-map [backspace] [?\C-h]) (define-key canna-minibuffer-mode-map [delete] [?\C-d]) )) (global-set-key "\C-\\" 'canna-undo) ) ) |
おまけその2:unix環境で利用する場合、cannaを利用するyc.elをportsやパッケージから導入しておけば利用できるようになります。
(setq yc-stop-chars "") (setq yc-canna-lib-path "/usr/local/lib/") (setq yc-canna-dic-path "/usr/local/share/canna/dic") ; (setq-default yc-rK-trans-key "\C-j") (cond ((not (featurep 'meadow)) (setq-default yc-use-color t) ) ) (load "yc") (global-yc-mode) (define-key yc-edit-mode-map "\177" 'yc-edit-backward-delete-char) (define-key yc-edit-mode-map "\C-h" 'yc-edit-backward-delete-char) (global-set-key [\C-henkan] 'yc-rK-trans) ;(global-set-key "\C-o" 'toggle-input-method) |
Ctrl-x Ctrl-f(以降\C-x\C-fと表記) | ファイルを開く。
この場合、\C-iやTabキーで既にあるファイル名の場合補完することが出来、間違うことなく入力できます。 試しに~/.emacsを開いてみましょう。 |
\C-x\C-s | 上書き保存が出来ます。 |
\C-x\C-w | ファイル名を指定して保存。同名のファイルが存在すると、上書きして良いかどうか確認してきます。 |
\C-xk | 現在編集しているファイルを破棄。 保存していない場合は、本当に破棄して良いかどうか確認してきます。良ければ'yes'と入力し、ダメな場合は\C-gを入力して取り消しましょう。 |
\C-x\C-b | 現在編集しているファイルの一覧を表示。カーソル上下で選択してReturn入力で編集ファイルを選択できます。 |
\C-xb | 編集中ファイル名(バッファ名)を直接入力して選択。 |
Ctrl-x 3(\C-x3)(Ctrl-xの次にただの3 | ウィンドウを中央で縦割り。
ソースコードの基本は1行80文字なので、startemacs.batでは縦割りした状態に合わせたウィンドウサイズになっているはずです。 |
\C-x2 | ウィンドウを横割り。同じファイルの異なる場所を同時に見ることが出来るようになります。 |
\C-xo | 分割したウィンドウ間を移動。 |
\C-x\C-n | 次の分割に移動。筆者が提供したドットファイル群でカスタマイズした状態で使用できます。 |
\C-x\C-p | 前の分割に移動。筆者が提供したドットファイル群でカスタマイズした状態で使用できます。 |
\C-x_ | 分割ウィンドウを1行ずつ縮める。 |
\C-x^ | 分割ウィンドウを1行ずつ広げる。 |
'\C-u繰り返し数' | \C-x_や\C-^の前に入力することにより、指定行数だけ繰り返して縮めたり広げたりすることが出来ます。 |
\C-f | 一文字右に進む。 |
\C-b | 一文字左に戻る。 |
\C-n | 次の行に行く。 |
\C-p | 手前の行に戻る。 |
\C-a | 行頭に戻る。 |
\C-e | 行末に行く。 | \M-f | 一語右に進む。
| \M-b | 一語左に戻る。 |
\C-\M-n(Ctrl-Alt-n) | カーソルを次の開き括弧に対応した閉じ括弧に移動する。 |
\C-\M-p(Ctrl-Alt-p) | カーソルを手前の閉じ括弧に対応した開き括弧に移動する。 |
\C-v | 1ページ下に移動する。 |
\M-v(Alt-v) | 1ページ上に移動する。 |
\C-\M-v(Ctrl-Alt-v) | 次の分割ウィンドウを1ページ下にスクロールする。 |
\M-<(Alt-Shift-,)(\M-\S-,) | ファイルの先頭に移動する。 |
\M->(Alt-Shift-.)(\M-\S-.) | ファイルの最後に移動する。 |
\C-l(コントロールL) | (画面が文字化けした際などに)ウィンドウを再描画する。 |
BackSpaceキーや\C-h | 左一文字削除。カスタマイズした状態で使用できます。 |
Deleteキーや\C-d | カーソル位置の一文字削除 |
\C-\M-h(Ctrl-Alt-h) | カーソルの左一語をまとめて削除。
カスタマイズした状態。良く使用するキーですのでカスタマイズしました。 ただしAlt-BackSpaceなら使用できますが、Ctrl-Alt-BackSpaceはUNIX用のX Window Systemを強制終了させるキーなので気を付けてください。 |
Tabキーや\C-i | 行頭に自動でタブ入力(自動インデントが効果的です) |
\M-i(Alt-i) | タブをひとつだけ直接入力する。 |
\C-q | 次に入力したキーを直接入力する。 (コントロールコードを直接入力したい場合に使用します。) |
\C-m | 改行コードを入力。 |
\C-; | コメント(注釈)入力。 |
\M-m(Alt-m) | 現在行を折り返さずにすっ飛ばして新規行の作成を行なう。カスタマイズした状態で使用できますが、これは入力が楽です。 |
\M-o | 現在行の手前に新規行を追加する。同様にカスタマイズした状態です。 |
\M-/ | 入力中の文字を元に補完入力を行なう。一度入力した長い単語を再入力する場合、特にソースコード入力時に便利です。 |
\M-g | 指定行番号にジャンプする。同様にカスタマイズした状態です。 |
\C-_や \C-\\ | アンドゥ。 連続でアンドゥできますが、カーソル移動などでアンドゥを一度止めると、次からはアンドゥ操作に対するアンドゥ(リドゥ)になるので気を付けてください。 実際に操作して慣れましょう。 |
'\C- '(Ctrl-Space) | 範囲指定開始(マークセット) |
\C-w | カット |
\M-w | コピー |
\C-y | ペースト |
\C-\M-\\(Ctrl-Alt-\) | 自動インデント(桁揃え)する。 |
\C-xnn | 範囲指定した領域に表示を狭める。 |
\C-xnw | 表示を狭めていたのを一段解除する。 |
\C-s | インクリメンタルサーチの次を検索する状態にする。 |
\C-r | 手前を検索する状態にする。 |
リターンキー(Enter)や、\C-m | 検索を終了する。 |
\C-g | カーソルを検索開始位置に戻す。\C-gはこの他にも、あらゆる状態をキャンセルし、標準状態に戻すことが出来ます。 |
\M-%(Alt-Shift-5)(\M-\S-5) | 単純モードで置換を行なう。 |
\C-\M-%(\C-\M-\S-5) | 正規表現モードで置換を行なう。 |
^ | 行頭にマッチ(一致)する。 |
$ | 行末にマッチする。 |
. | 任意の1文字にマッチする。 |
* | 直前の正規表現を繰り返し(0回以上)マッチする。 |
\( | 範囲指定開始。 |
\) | 範囲指定終了。 |
\数字(1-9) | 範囲指定でマッチした文字列に置き換える。 数字は、括弧が複数使用できるので、複数ある左括弧の順番を指定します。 |
正規表現例:
\C-\M-\S-5
\(<br>\)
\1<!-- test -->
これで、<br>を、<br><!-- test -->に置き換える事が出来ます。
応用すれば、自由に置換文字列を設定する事が出来る様になります。
\C-xd | diredディレクトリ編集モードを起動する。 |
n | カーソルを一行下に移動する。 |
p | カーソルを一行上に移動する。 |
f | カーソル位置のファイルを開く。 |
+ | ディレクトリを新規作成する。 |
= | diffコマンドを使用し、ファイル一致比較する。 |
!(\S-1) | ファイルを引き数にして指定コマンドを実行する。 |
\M-!(\M-\S-1) | 指定コマンドを実行する。 |
d | ファイルに削除マークを付ける。 |
~ | バックアップファイル(ファイル名の最後に'~'マークの付いたファイル)すべてに削除マークを付ける。 |
x | 削除マークの付いたファイルを削除する。 |
m | ファイルにマークを付ける。 |
C | マークの付いたファイルをコピーする。 |
R | マークの付いたファイルを移動する。 |
Alt-x(\M-x) | emacs-lispファンクションを直接呼び出す。 プロンプトに対してファンクション名を入力することが出来ます。 ここでTabキーや\C-iを押すことにより、候補一覧が表示されます。 |
\M-xdescribe-bindings | キーバインド(キー割り当て)一覧を表示する。 モード毎にバインディングが異なるので注意。 |
\M-xrecover-file | emacsが異常終了した場合に、編集中だったファイルを開いてからこのコマンドを実行すると、#で始まる一時保存ファイルから内容を復元することが出来る。 |
\C-x\C-mf | 保存する漢字コードや行末コードを指定する。 |
\C-x\C-e | カーソル左のemacs-lispを直接実行する。
計算関数例:(+ 256 128)の右括弧の右側にカーソルを置き、\C-x\C-eを入力することにより計算が実行できます。 |
\M-xcompile | makeコマンドを実行してコンパイルする。 |
\C-x`(Ctrl-x Shift-@) | makeコマンドのエラー行にジャンプする。超便利。 |
\M-xgdb | gdbコマンドを実行してデバッグする。デバッグ方法はファイヤーボールの項で説明(する予定に)しています。 |
iso-2022-jp | JIS規格の通信用14bits漢字コードで、各byteの頭1bitを使用しない(0の)漢字コードになっています。 ちなみに日本語とAsciiコードの切り替えにはエスケープシーケンス(ESCコードから始まる制御コード列)を使用したコードです。 |
sjis | 日本語MS-DOSの時代から続く、日本語シフトJIS漢字コードで、7bits Asciiコードと、1byte半角カナ、その隙間に2bytesの日本語のコードです。 |
euc-jp | 昔の日本語UNIX系OSで使用されていた日本語EUCコードで、7bits Asciiコードと、各byteの頭1bitに1を立てた日本語のコードです。 |
各漢字コード名の末に下表の文字列を付加する事により、行末コードを指定する事が出来ます。
-dos | CR/LFのDOS行末コード |
-unix | LFのみのUNIX行末コード |
-mac | CRのみのMac行末コード |
emacsはMetaキーを多用するエディターなのですが、PCではAltキーしか無かった時代が長く、AltキーをMetaキーとして代用して使用しています。このため、\M-xなどのMはMetaの略なのです。
ちなみに、Esc-x(\M-x)など、Escキーを押すことにより、Metaキーの代用にもなります。
# Makefile for level-1 magic fireball. CXX = i686-w64-mingw32-g++ CXXFLAGS= -g -ggdb -DDEBUG -Wall CXXFLAGS+= -I../../gl_extloader2 LDFLAGS = -L../../gl_extloader2/MSYS32/Release LIBS = -lgl_extloader LIBS += -lfreeglut LIBS += -lGLU32 -lopengl32 -lwsock32 -lwinmm SRCS = fireball.cc firesub.cc vec.cc main.cc OBJS = $(SRCS:.cc=.o) PROGNAME= fireball PROGFILE= $(PROGNAME).exe VERSION =snapshot ifeq ($(OSTYPE),msys) Windows =true endif ifeq ($(OSTYPE),cygwin) Windows =true endif ifdef Windows ARCHNAME = $(PROGNAME)-$(VERSION)-`date +%Y%m%d` else ARCHNAME = $(PROGNAME)-$(VERSION)-`date -j +%Y%m%d` endif ARCHFILES = $(PROGFILE) ARCHFILES += libfreeglut.dll ARCHFILES += libgcc_s_dw2-1.dll libwinpthread-1.dll libstdc++-6.dll all: $(PROGNAME) archive:: #librel rel -rm -f $(ARCHNAME).zip zip $(ARCHNAME).zip $(ARCHFILES) $(PROGNAME): $(OBJS) $(CXX) -o $@ $(LDFLAGS) $^ $> $(LIBS) clean: -rm $(OBJS) *~ .cc.o: $(CXX) $(CXXFLAGS) -c -o $@ $< |
struct vec3_t { float x, y, z; }; struct vec4_t { float x, y, z, w; }; struct mat4_t { vec4_t row[4]; }; struct col4_t { float r, g, b, a; }; struct projection_t { double m_left, m_right; double m_bottom, m_top; double m_near, m_far; }; vec4_t Let4(const vec3_t &vec3, float w=1.0f); vec3_t Let3(const vec4_t &vec4); float Length( const vec3_t &axis); // vec3_t Dot( const vec3_t &v1, const vec3_t &v2); vec3_t Cross( const vec3_t &v1, const vec3_t &v2); vec4_t Multiply( const vec4_t &vec4, const mat4_t &mat); vec4_t Multiply( const mat4_t &mat, const vec4_t &vec4); mat4_t RotateMatrix( const vec3_t &axis1, const vec3_t &axis2); mat4_t getPerspectiveMatrix( const projection_t &fr); extern const mat4_t Identity; extern const vec3_t vecz; extern const col4_t quarterblue; extern const col4_t halforange; |
#include <cmath> using namespace std; #include "vec.h" const mat4_t Identity = {{ { 1,0,0,0}, { 0,1,0,0}, { 0,0,1,0}, { 0,0,0,1}, }}; const vec3_t vecz = { 0,0,1 }; const col4_t quarterblue = { 0,0,0.25,1.0 }; const col4_t halforange = { 0.5,0.25,0,1.0 }; vec4_t Let4(const vec3_t &vec3, float w) { vec4_t result; result.x = vec3.x; result.y = vec3.y; result.z = vec3.z; result.w = w; return result; } vec3_t Let3(const vec4_t &vec4) { vec3_t result; result.x = vec4.x; result.y = vec4.y; result.z = vec4.z; return result; } float Length( const vec3_t &axis) { return sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z); } vec3_t Cross( const vec3_t &v1, const vec3_t &v2) { vec3_t result; result.x = v1.y * v2.z - v1.z * v2.y; result.y = v1.z * v2.x - v1.x * v2.z; result.z = v1.x * v2.y - v1.y * v2.x; return result; } vec4_t Multiply( const vec4_t &vec4, const mat4_t &mat) { vec4_t result; result.x= vec4.x * mat.row[0].x + vec4.y * mat.row[1].x + vec4.z * mat.row[2].x + vec4.w * mat.row[3].x; result.y= vec4.x * mat.row[0].y + vec4.y * mat.row[1].y + vec4.z * mat.row[2].y + vec4.w * mat.row[3].y; result.z= vec4.x * mat.row[0].z + vec4.y * mat.row[1].z + vec4.z * mat.row[2].z + vec4.w * mat.row[3].z; result.w= vec4.x * mat.row[0].w + vec4.y * mat.row[1].w + vec4.z * mat.row[2].w + vec4.w * mat.row[3].w; return result; } vec4_t Multiply( const mat4_t &mat, const vec4_t &vec4) { vec4_t result; result.x= mat.row[0].x * vec4.x + mat.row[0].y * vec4.y + mat.row[0].z * vec4.z + mat.row[0].w * vec4.w; result.y= mat.row[1].x * vec4.x + mat.row[1].y * vec4.y + mat.row[1].z * vec4.z + mat.row[1].w * vec4.w; result.z= mat.row[2].x * vec4.x + mat.row[2].y * vec4.y + mat.row[2].z * vec4.z + mat.row[2].w * vec4.w; result.w= mat.row[3].x * vec4.x + mat.row[3].y * vec4.y + mat.row[3].z * vec4.z + mat.row[3].w * vec4.w; return result; } mat4_t RotateMatrix( const vec3_t &axis1, const vec3_t &axis2) { vec3_t axis = Cross(axis1, axis2); float length = Length(axis); if (!length) return Identity; float length_1 = 1.0 / length; axis.x *= length_1; axis.y *= length_1; axis.z *= length_1; float a = M_PI * 0.5 * length; const float x = axis.x; const float y = axis.y; const float z = axis.z; const float cosa = cosf(a); const float sina = sinf(a); mat4_t result = {{ {x*x+(1.0f-x*x)*cosa, x*y*(1.0f-cosa)+z*sina, y*x*(1.0f-cosa)-y*sina,0}, {x*y*(1.0f-cosa)-z*sina, y*y+(1.0f-y*y)*cosa, y*z*(1.0f-cosa)-x*sina,0}, {y*z*(1.0f-cosa)+y*sina, y*z*(1.0f-cosa)-x*sina, z*z+(1.0f-z*z)*cosa,0}, { 0, 0, 0, 1 }, }}; return result; } mat4_t getPerspectiveMatrix( const projection_t &fr) { mat4_t mat = {{ {(float)(fr.m_near*2.0 / (fr.m_right - fr.m_left)), 0, 0, 0}, {0, (float)(fr.m_near*2/(fr.m_top-fr.m_bottom)), 0, 0}, {(float)((fr.m_right+fr.m_left)/(fr.m_right-fr.m_left)), (float)((fr.m_top+fr.m_bottom)/(fr.m_top-fr.m_bottom)), (float)(-(fr.m_far+fr.m_near)/(fr.m_far-fr.m_near)), -1}, {0, 0, (float)(-2*fr.m_far*fr.m_near/(fr.m_far-fr.m_near)), 0} }}; return mat; } |
#include <list> using namespace std; size_t RotatedSphereVertex( float *ptr, size_t vertex_items, size_t xedges, size_t yedges, double lapse, const vec3_t &topvec, const vec3_t ¢er); size_t RotatedSphereElement( unsigned int *ptr, size_t vertexbase, size_t xedges, size_t yedges); size_t RotatedCornVertex( float *ptr, size_t vertex_items, size_t xedges, size_t yedges, const vec3_t &topvec, const vec3_t &axis, const vec3_t ¢er); size_t RotatedCornElement( unsigned int *ptr, size_t vertexbase, size_t xedges, size_t yedges); struct firevent_t { enum e_evtype_t { STARTBURN, ENDBURN, CONTINUE }; e_evtype_t eventype; double time; vec3_t pos; }; class firesub_t { protected: vec3_t center, inertial; double time; //lapse time(msec) from the start. // size_t begin, cur; bool is_burning; // vector<fireaxis_t> axes; //center axis of fire burning. list<firevent_t> event; public: firesub_t(); ~firesub_t(); void Center( const vec3_t &position); void Operation( const vec3_t &movement); //add the inertial of fireball. void StartBurn(); void EndBurn(); void ContinueBurn(); void Lapse( double lapse); }; |
#include <cmath> #include <iostream> using namespace std; #include "vec.h" #include "firesub.h" // #define AXIS_COUNT 1000 //1.0sec. size_t RotatedSphereVertex( float *ptr, size_t vertex_items, size_t xedges, size_t yedges, double lapse, const vec3_t &topvec, const vec3_t ¢er) { // float length = Length(axis); // float length_1 = 1.0 / length; // vec3_t ax = {axis.x*length_1, axis.y*length_1, axis.z*length_1}; mat4_t mat = RotateMatrix( vecz, topvec ); mat.row[3] = Let4(center); float pi_edges = M_PI / float(yedges-1); float pi_2_edges = M_PI * 2.0f / float(xedges); for (size_t v=0; v< yedges-2; v++) { for (size_t u=0; u< xedges; u++) { size_t index = (v*xedges+u+1) * vertex_items; vec3_t *vec3ptr= (vec3_t*)&ptr[index]; col4_t *col4ptr= (col4_t*)&ptr[index+3]; *col4ptr = quarterblue; vec3_t vec3; float latitude= float(v+1) * pi_edges; float longitude= float(u) * pi_2_edges; vec3.x = cos(longitude) * sin(latitude) * lapse; vec3.y = sin(longitude) * sin(latitude) * lapse; vec3.z = cos(latitude) * lapse; // #ifdef DEBUG // *vec3ptr= vec3; // vec3ptr->x += center.x; // vec3ptr->y += center.y; // vec3ptr->z += center.z; // #else *vec3ptr= Let3(Multiply( Let4(vec3), mat)); // #endif // cerr << "u(" << u << "), v(" << (v+1) << ") = (" // << vec3ptr->x << ", " << vec3ptr->y << ", " << vec3ptr->z // << ")" << endl; } } size_t index = ((yedges-2)*xedges+1) * vertex_items; vec3_t *vec3ptr= (vec3_t*)&ptr[index]; col4_t *col4ptr= (col4_t*)&ptr[index+3]; vec3_t vec3; *col4ptr = quarterblue; vec3.x = center.x - topvec.x * lapse; vec3.y = center.y - topvec.y * lapse; vec3.z = center.z - topvec.z * lapse; *vec3ptr= vec3; // *vec3ptr= Let3(Multiply( Let4(vec3), mat)); // cerr << "u(" << xedges << "), v(" << (yedges-1) << ") = (" // << vec3ptr->x << ", " << vec3ptr->y << ", " << vec3ptr->z // << ")" << endl; index = 0; vec3ptr = (vec3_t*)&ptr[index]; col4ptr = (col4_t*)&ptr[index+3]; *col4ptr = quarterblue; vec3.x = center.x + topvec.x * lapse; vec3.y = center.y + topvec.y * lapse; vec3.z = center.z + topvec.z * lapse; *vec3ptr= vec3; // *vec3ptr= Let3(Multiply( Let4(vec3), mat)); // cerr << "u(" << 0 << "), v(" << 0 << ") = (" // << vec3ptr->x << ", " << vec3ptr->y << ", " << vec3ptr->z // << ")" << endl; // cerr << endl; return (yedges-2)*xedges+2; } size_t RotatedSphereElement( unsigned int *ptr, size_t vertexbase, size_t xedges, size_t yedges) { unsigned int *optr = ptr; for (size_t i=0; i< xedges; i++) { ptr[i*2+0] = vertexbase; ptr[i*2+1] = vertexbase + i + 1; } ptr[xedges*2+0] = vertexbase; ptr[xedges*2+1] = vertexbase + 0 + 1; ptr[xedges*2+2] = -1; ptr += xedges*2+3; for (size_t v=0; v< yedges-3; v++) { for (size_t u=0; u< xedges; u++) { // ptr[(xedges*v+u)*2+v*3+0] = vertexbase + xedges*(v+0) + u + 1; // ptr[(xedges*v+u)*2+v*3+1] = vertexbase + xedges*(v+1) + u + 1; *ptr++ = vertexbase + xedges*(v+0) + u + 1; *ptr++ = vertexbase + xedges*(v+1) + u + 1; } // ptr[xedges*(v+1)*2+v*3+0] = vertexbase + xedges*(v+0) + 1; // ptr[xedges*(v+1)*2+v*3+1] = vertexbase + xedges*(v+1) + 1; // ptr[xedges*(v+1)*2+v*3+2] = -1; *ptr++ = vertexbase + xedges*(v+0) + 1; *ptr++ = vertexbase + xedges*(v+1) + 1; *ptr++ = -1; } // ptr += xedges*2*(yedges-3) + yedges*3; for (size_t i=0; i< xedges; i++) { ptr[i*2+0] = vertexbase + xedges * (yedges-3) + i + 1; ptr[i*2+1] = vertexbase + xedges * (yedges-2) + 1; } ptr[xedges*2+0] = vertexbase + xedges * (yedges-3) + 1; ptr[xedges*2+1] = vertexbase + xedges * (yedges-2) + 1; ptr[xedges*2+2] = -1; ptr += xedges*2+3; // for (unsigned int *p=optr; p< ptr; p++) { // cerr << (*p) << endl; // } // cerr << endl; return ptr - optr; } size_t RotatedCornVertex( float *ptr, size_t vertex_items, size_t xedges, size_t yedges, const vec3_t &topvec, const vec3_t &axis, const vec3_t ¢er) { float length = Length(axis); float length_1 = 1.0 / length; vec3_t ax = {axis.x*length_1, axis.y*length_1, axis.z*length_1}; float radius = 0.5f; //Length(axis); mat4_t mat = RotateMatrix( vecz, ax ); mat.row[3] = Let4(center); float pi_edges = M_PI / float(yedges-1); float pi_2_edges = M_PI * 2.0f / float(xedges); for (size_t v=0; v< (size_t)((yedges-2)*0.5+0.5); v++) { for (size_t u=0; u< xedges; u++) { size_t index = (v*xedges+u+1) * vertex_items; vec3_t *vec3ptr= (vec3_t*)&ptr[index]; col4_t *col4ptr= (col4_t*)&ptr[index+3]; *col4ptr = quarterblue; vec3_t vec3; float latitude= float(v+(size_t)((yedges-2)*0.5+0.5)) * pi_edges; float longitude= float(u) * pi_2_edges; vec3.x = cos(longitude) * sin(latitude) * radius; vec3.y = sin(longitude) * sin(latitude) * radius; vec3.z = cos(latitude) * radius; *vec3ptr= Let3(Multiply( Let4(vec3), mat)); // cerr << "index(" << index // << "): u(" << u << "), v(" << (v+1) << ") = (" // << vec3ptr->x << ", " << vec3ptr->y << ", " << vec3ptr->z // << ")" << endl; } } size_t index = ((size_t)((yedges-2)*0.5+0.5)*xedges+1) * vertex_items; vec3_t *vec3ptr= (vec3_t*)&ptr[index]; col4_t *col4ptr= (col4_t*)&ptr[index+3]; vec3_t vec3; *col4ptr = quarterblue; vec3.x = center.x - ax.x * 0.5; vec3.y = center.y - ax.y * 0.5; vec3.z = center.z - ax.z * 0.5; *vec3ptr= vec3; // *vec3ptr= Let3(Multiply( Let4(vec3), mat)); // cerr << "index(" << index // << "): u(" << xedges << "), v(" << (size_t)((yedges-2)*0.5+0.5) // << ") = (" << vec3ptr->x << ", " << vec3ptr->y << ", " << vec3ptr->z // << ")" << endl; index = 0; vec3ptr = (vec3_t*)&ptr[index]; col4ptr = (col4_t*)&ptr[index+3]; *col4ptr = halforange; vec3.x = center.x + axis.x; vec3.y = center.y + axis.y; vec3.z = center.z + axis.z; *vec3ptr= vec3; // *vec3ptr= Let3(Multiply( Let4(vec3), mat)); // cerr << "u(" << 0 << "), v(" << 0 << ") = (" // << vec3ptr->x << ", " << vec3ptr->y << ", " << vec3ptr->z // << ")" << endl; // cerr << endl; return (size_t)((yedges-2)*0.5+0.5)*xedges+2; } size_t RotatedCornElement( unsigned int *ptr, size_t vertexbase, size_t xedges, size_t yedges) { unsigned int *optr = ptr; for (size_t i=0; i< xedges; i++) { ptr[i*2+0] = vertexbase; ptr[i*2+1] = vertexbase + i + 1; } ptr[xedges*2+0] = vertexbase; ptr[xedges*2+1] = vertexbase + 0 + 1; ptr[xedges*2+2] = -1; ptr += xedges*2+3; // unsigned int *o2ptr = ptr; for (size_t v=0; v< (size_t)((yedges-3)*0.5+0.5); v++) { // cerr << "v: " << v << endl; for (size_t u=0; u< xedges; u++) { // ptr[(xedges*v+u)*2+v*3+0] = vertexbase + xedges*(v+0) + u + 1; // ptr[(xedges*v+u)*2+v*3+1] = vertexbase + xedges*(v+1) + u + 1; *ptr++ = vertexbase + xedges*(v+0) + u + 1; *ptr++ = vertexbase + xedges*(v+1) + u + 1; } // ptr[xedges*(v+1)*2+v*3+0] = vertexbase + xedges*(v+0) + 1; // ptr[xedges*(v+1)*2+v*3+1] = vertexbase + xedges*(v+1) + 1; // ptr[xedges*(v+1)*2+v*3+2] = -1; *ptr++ = vertexbase + xedges*(v+0) + 1; *ptr++ = vertexbase + xedges*(v+1) + 1; *ptr++ = -1; } // cerr << "ptr - o2ptr: " << (ptr - o2ptr) << endl; // ptr+=xedges*2*(size_t)((yedges-3)*0.5+0.5) + (size_t)(yedges*0.5+0.5)*3; for (size_t i=0; i< xedges; i++) { ptr[i*2+0] = vertexbase + xedges * (size_t)((yedges-3)*0.5+0.5) +i +1; ptr[i*2+1] = vertexbase + xedges * (size_t)((yedges-3)*0.5+1.5) + 1; } ptr[xedges*2+0] = vertexbase + xedges * (size_t)((yedges-3)*0.5+0.5) + 1; ptr[xedges*2+1] = vertexbase + xedges * (size_t)((yedges-3)*0.5+1.5) + 1; ptr[xedges*2+2] = -1; ptr += xedges*2+3; // for (unsigned int *p=optr; p< ptr; p++) { // cerr << (*p) << endl; // } // cerr << endl; return ptr - optr; } firesub_t::firesub_t() :time(0), is_burning(false) { center.x = center.y = center.z = 0; inertial.x = inertial.y = inertial.z = 0; } firesub_t::~firesub_t() { return; } void firesub_t::Center( const vec3_t &position) { center = position; } //add the inertial of fireball. void firesub_t::Operation( const vec3_t &movement) { if (is_burning) { // EndBurn(); // StartBurn(); ContinueBurn(); } inertial.x += movement.x; inertial.y += movement.y; inertial.z += movement.z; } void firesub_t::StartBurn() { if (is_burning) { ContinueBurn(); return; } event.push_back(firevent_t()); list<firevent_t>::iterator it = --event.end(); it->eventype = firevent_t::STARTBURN; it->time = time; it->pos = center; is_burning = true; } void firesub_t::EndBurn() { event.push_back(firevent_t()); list<firevent_t>::iterator it = --event.end(); it->eventype = firevent_t::ENDBURN; it->time = time; it->pos = center; is_burning = false; } void firesub_t::ContinueBurn() { // if (!is_burning) // return; event.push_back(firevent_t()); list<firevent_t>::iterator it = --event.end(); it->eventype = firevent_t::CONTINUE; it->time = time; it->pos = center; } void firesub_t::Lapse( double lapse) { center.x += inertial.x * lapse; center.y += inertial.y * lapse; center.z += inertial.z * lapse; time += lapse; for (list<firevent_t>::iterator it = event.begin(); it != event.end();) { it->pos.y += lapse; if (time - it->time > 1.0) { switch (it->eventype) { case firevent_t::STARTBURN: case firevent_t::CONTINUE: { double diff = time - it->time - 1.0; if (diff < 0.0) { cerr << "Error diff < 0.0" << endl; } it->time += diff; it->pos.y -= diff; it->pos.x += inertial.x * diff; it->pos.y += inertial.y * diff; it->pos.z += inertial.z * diff; } break; case firevent_t::ENDBURN: event.erase(event.begin(), ++it); continue; } } ++it; } } |
class gl_program_t { size_t initcount; GLint vertex_shader, fragment_shader; GLint program; public: gl_program_t(); ~gl_program_t(); bool Init( const char *vertex_shader_code, size_t vertex_shader_len, const char *fragment_shader_code, size_t fragment_shader_len); void Destroy(); GLuint getUniformLocation( const char *name); void Use(); void Unuse(); }; struct fireaxis_t { double startime; double endtime; //0 is now burning. vec3_t top, center; //top, center of fire position. size_t vertex, element; //vertex index, element index. size_t end_vertex, end_element; //vertex index, element index. enum e_firetype_t { //fire type of upper half. FIRE_CORN, FIRE_CYLINDER, FIRE_SPHERE, }; e_firetype_t firetype; }; class fireball_t : private firesub_t { public: static gl_program_t s_gl_program; static GLuint s_model_location, s_inv_location, s_proj_location; protected: bool inited; GLuint vertex_array, array1, array2, element_array; size_t vertices; size_t elements; // double startime; public: fireball_t(); ~fireball_t(); void Init(); void Destroy(); using firesub_t::Center; using firesub_t::Operation; using firesub_t::Lapse; using firesub_t::StartBurn; using firesub_t::EndBurn; using firesub_t::ContinueBurn; const vec3_t& getCenter()const{return center;} void KeyFrame( size_t xedges = 18, size_t yedges = 9); void Draw( const vec3_t &position, double rate)const; }; |
// fireball.cc - a fireball shot demo program. #include <cassert> #include <iostream> using namespace std; #include <gl_extloader.h> #include "vec.h" #include "firesub.h" #include "fireball.h" gl_program_t fireball_t::s_gl_program; GLuint fireball_t::s_model_location=0; GLuint fireball_t::s_inv_location=0; GLuint fireball_t::s_proj_location=0; // static GLsizei vertex_count=0, element_count=0; #define VERTEX_ITEMS 10 static const char s_vertex_shader_code[] = "#version 330\n\ \n\ layout (location = 0) in vec3 Position;\n\ layout (location = 1) in vec4 Color;\n\ layout (location = 2) in vec3 Normal;\n\ layout (location = 3) in vec2 TexCoord;\n\ \n\ out vec3 vertexPosition;\n\ out vec3 vertexNormal;\n\ out vec4 vertexColor;\n\ out vec2 vertexTexCoord;\n\ \n\ uniform mat4 Modelview;\n\ uniform mat4 invModelview;\n\ uniform mat4 Projection;\n\ uniform float BlendRate;\n\ \n\ void main()\n\ {\n\ vertexPosition = vec3(Modelview * vec4(Position,1.0));\n\ vertexNormal = vec3(vec4(Normal,0.0) * invModelview);\n\ vertexColor = Color;\n\ vertexTexCoord = TexCoord;\n\ gl_Position = Projection * vec4(vertexPosition,1.0);\n\ }\n\ "; static const char s_fragment_shader_code[] = "#version 330\n\ \n\ in vec3 vertexPosition;\n\ in vec3 vertexNormal;\n\ in vec4 vertexColor;\n\ in vec2 vertexTexCoord;\n\ \n\ layout (location = 0) out vec4 fragmentColor;\n\ \n\ uniform vec3 LightPosition;\n\ uniform float Shininess;\n\ uniform vec4 specularColor;\n\ \n\ void main()\n\ {\n\ // vec3 eyeVector = normalize(LightPosition - vertexPosition);\n\ // vec3 v = normalize(-vertexPosition);\n\ // vec3 r = reflect( -eyeVector, vertexNormal);\n\ // vec4 diffuse = vertexColor * max( dot(eyeVector,vertexNormal), 0.0);\n\ // vec4 specular = vec4(1.0, 1.0, 1.0, 1.0) * pow( max( dot(r,v), 0.0 ), Shininess);\n\ // fragmentColor = diffuse + specular;\n\ fragmentColor = vertexColor;\n\ }\n\ "; GLint InitShader( GLuint shader_type, GLchar *shader_code, GLsizei code_size) { GLint shader; const GLchar* string_buffers[1]; GLsizei size_buffers[1]; GLuint status; GLsizei loglength; GLchar *logbuffer; shader = glCreateShader( shader_type); string_buffers[0] = shader_code; size_buffers[0] = code_size; glShaderSource( shader, 1, string_buffers, size_buffers); glCompileShader( shader); glGetShaderiv( shader, GL_COMPILE_STATUS, (GLint*)&status); if (!status) { glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &loglength); logbuffer = new char[loglength+1]; glGetShaderInfoLog( shader, loglength, &loglength, logbuffer); logbuffer[loglength] = '\0'; cerr << "shader compile error.\n" << logbuffer << endl; delete[] logbuffer; } return shader; } GLint InitProgram( size_t count, const GLint *shaders) { GLint program_object; GLuint status; GLsizei loglength; GLchar *logbuffer; program_object = glCreateProgram(); for (size_t i=0; i< count; i++) { glAttachShader( program_object, shaders[i]); } glLinkProgram(program_object); glGetProgramiv( program_object, GL_LINK_STATUS, (GLint*)&status); if (!status) { glGetProgramiv( program_object, GL_INFO_LOG_LENGTH, &loglength); logbuffer = new char[loglength+1]; glGetProgramInfoLog( program_object, loglength, &loglength, logbuffer); logbuffer[loglength] = '\0'; cerr << "program link error.\n" << logbuffer << endl; delete[] logbuffer; } return program_object; } gl_program_t::gl_program_t() :initcount(0), vertex_shader(0), fragment_shader(0), program(0) { } gl_program_t::~gl_program_t() { return; } bool gl_program_t::Init( const char *vertex_shader_code, size_t vertex_shader_len, const char *fragment_shader_code, size_t fragment_shader_len) { if (initcount++) return false; vertex_shader = InitShader( GL_VERTEX_SHADER, (GLchar*)vertex_shader_code, vertex_shader_len); fragment_shader = InitShader( GL_FRAGMENT_SHADER, (GLchar*)fragment_shader_code, fragment_shader_len); GLint shaders[2]; shaders[0] = vertex_shader; shaders[1] = fragment_shader; program = InitProgram( 2, shaders); return true; } void gl_program_t::Destroy() { if (--initcount) return; glDetachShader( program, vertex_shader); glDetachShader( program, fragment_shader); glDeleteShader( vertex_shader); glDeleteShader( fragment_shader); glDeleteProgram( program); } GLuint gl_program_t::getUniformLocation( const char *name) { return glGetUniformLocation( program, name); } void gl_program_t::Use() { glUseProgram(program); } void gl_program_t::Unuse() { glUseProgram(0); } fireball_t::fireball_t() :inited(false), vertex_array(0), array1(0), array2(0), element_array(0), vertices(0), elements(0)//, startime(0) { return; } fireball_t::~fireball_t() { if (inited) Destroy(); } void fireball_t::Init() { if (inited) return; if (s_gl_program.Init( s_vertex_shader_code, sizeof(s_vertex_shader_code), s_fragment_shader_code, sizeof(s_fragment_shader_code))){ s_model_location = s_gl_program.getUniformLocation("Modelview"); s_inv_location = s_gl_program.getUniformLocation("invModelview"); s_proj_location = s_gl_program.getUniformLocation("Projection"); } glGenVertexArrays( 1, &vertex_array); glGenBuffers( 1, &array1); glGenBuffers( 1, &array2); glGenBuffers( 1, &element_array); inited =true; } void fireball_t::Destroy() { if (!inited) return; s_gl_program.Destroy(); glDeleteBuffers( 1, &element_array); glDeleteBuffers( 1, &array2); glDeleteBuffers( 1, &array1); glDeleteVertexArrays(1, &vertex_array); inited =false; } void fireball_t::KeyFrame( size_t xedges, size_t yedges) { if (!inited) return; vertices = 0; elements = 0; list<fireaxis_t> fireaxes; bool burning = false; list<firevent_t>::const_iterator prev_it = event.end(); // double startime = time; for( list<firevent_t>::const_iterator it = event.begin(); it != event.end(); ++it) { switch (it->eventype) { case firevent_t::STARTBURN: assert(!burning); burning = true; // startime = it->time; break; case firevent_t::ENDBURN: { assert(burning); burning = false; fireaxes.push_back(fireaxis_t()); list<fireaxis_t>::iterator fait = --fireaxes.end(); fait->startime = prev_it->time; fait->endtime = it->time; fait->top = prev_it->pos; fait->center = it->pos; // double wktime = it->time - startime; // assert(wktime >= 0.0); fait->vertex = vertices; fait->element = elements; switch (prev_it->eventype) { case firevent_t::STARTBURN: if (fait->endtime - fait->startime <= 0.5) { fait->firetype = fireaxis_t::FIRE_SPHERE; vertices += (yedges-2) * xedges + 2; elements += (xedges*2) * (yedges-1) + (yedges-3)*3 + 6; } else { fait->firetype = fireaxis_t::FIRE_CORN; vertices += (size_t)((yedges-2)*0.5+0.5) * xedges + 2; elements += (xedges*2) * (size_t)((yedges-3)*0.5+0.5+2.0) +(size_t)((yedges-3)*0.5+0.5)*3 +6; } break; case firevent_t::CONTINUE: fait->firetype = fireaxis_t::FIRE_CYLINDER; vertices += xedges; elements += (xedges+1) * 2 + 1; //add of restart index. break; case firevent_t::ENDBURN: assert(false); return; } fait->end_vertex = vertices; fait->end_element = elements; } break; case firevent_t::CONTINUE: { assert(burning); fireaxes.push_back(fireaxis_t()); list<fireaxis_t>::iterator fait = --fireaxes.end(); fait->startime = prev_it->time; fait->endtime = it->time; fait->top = prev_it->pos; fait->center = it->pos; fait->vertex = vertices; fait->element = elements; switch (prev_it->eventype) { case firevent_t::STARTBURN: if (fait->endtime - fait->startime <= 0.5) { fait->firetype = fireaxis_t::FIRE_SPHERE; vertices += (yedges-2) * xedges + 2; elements += (xedges*2) * (yedges-1) + (yedges-3)*3 + 6; } else { fait->firetype = fireaxis_t::FIRE_CORN; vertices += (size_t)((yedges-2)*0.5+0.5) * xedges + 2; elements += (xedges*2) * (size_t)((yedges-3)*0.5+0.5 +2) +(size_t)((yedges-3)*0.5+0.5)*3 +6; } break; case firevent_t::CONTINUE: fait->firetype = fireaxis_t::FIRE_CYLINDER; vertices += xedges; elements += (xedges+1) * 2 + 1; //add of restart index. break; case firevent_t::ENDBURN: assert(false); return; } fait->end_vertex = vertices; fait->end_element = elements; } break; } prev_it = it; } if (burning) { fireaxes.push_back(fireaxis_t()); list<fireaxis_t>::iterator fait = --fireaxes.end(); fait->startime = prev_it->time; fait->endtime = time; fait->top = prev_it->pos; fait->center = center; fait->vertex = vertices; fait->element = elements; switch (prev_it->eventype) { case firevent_t::STARTBURN: if (time - fait->startime <= 0.5) { fait->firetype = fireaxis_t::FIRE_SPHERE; vertices += (yedges-2) * xedges + 2; elements += (xedges*2) * (yedges-1) + (yedges-3)*3 + 6; } else { fait->firetype = fireaxis_t::FIRE_CORN; vertices += (size_t)((yedges-2)*0.5+0.5) * xedges + 2; elements += (xedges*2) * (size_t)((yedges-3)*0.5+0.5 +2.0) +(size_t)((yedges-3)*0.5+0.5)*3 +6; } break; case firevent_t::CONTINUE: fait->firetype = fireaxis_t::FIRE_CYLINDER; vertices += xedges; elements += (xedges+1) * 2 + 1; break; case firevent_t::ENDBURN: assert(false); return; } fait->end_vertex = vertices; fait->end_element = elements; } // size_t end = cur; // if (begin > cur) // end += axis.size(); // for (size_t i=begin; i< end; i++) { // size_t c = i % axis.size(); // double lapse = time - axis[c].startime; // if (axis[c].endtime) { //end burn. // double wktime = axis[c].endtime - axis[c].startime; // } // else { //burning now. // vertices = 1 + 16 * lapse; // } // } // glDeleteBuffers( 1, &array2); // glDeleteBuffers( 1, &array1); // glDeleteVertexArrays(1, &vertex_array); // glGenVertexArrays( 1, &vertex_array); // glGenBuffers( 1, &array1); // glGenBuffers( 1, &array2); glBindBuffer( GL_ARRAY_BUFFER, array1); glBufferData( GL_ARRAY_BUFFER, vertices*sizeof(GLfloat)*VERTEX_ITEMS, NULL, GL_DYNAMIC_DRAW); GLfloat *ptr1 = (GLfloat*)glMapBufferRange( GL_ARRAY_BUFFER, 0, vertices*sizeof(GLfloat)*VERTEX_ITEMS, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT); size_t v1=0; for (list<fireaxis_t>::const_iterator cfait = fireaxes.begin(); cfait != fireaxes.end(); ++cfait) { switch (cfait->firetype) { case fireaxis_t::FIRE_CORN: { size_t index = cfait->vertex*VERTEX_ITEMS; float *ptr = &ptr1[index]; vec3_t axis, topvec = {0,1,0}; axis.x = cfait->top.x - cfait->center.x; axis.y = cfait->top.y - cfait->center.y; axis.z = cfait->top.z - cfait->center.z; // cerr << "begin rotated corn vertex." << endl; size_t vtmp1 = RotatedCornVertex( ptr, VERTEX_ITEMS, xedges, yedges, topvec, axis, cfait->center); v1 += vtmp1; // cerr << "corn v1: " << v1 // << ", vtmp1: " << vtmp1 // << ", vertices: " << vertices << endl; assert( v1 <= cfait->end_vertex); } break; case fireaxis_t::FIRE_CYLINDER: break; case fireaxis_t::FIRE_SPHERE: { size_t index = cfait->vertex*VERTEX_ITEMS; float *ptr = &ptr1[index]; // vec3_t axis; // axis.x = cfait->top.x - cfait->center.x; // axis.y = cfait->top.y - cfait->center.y; // axis.z = cfait->top.z - cfait->center.z; // if (!axis.x && !axis.y && !axis.z) { // cerr << "axis is zero." << endl; // } // #ifdef DEBUG // axis.x *= 100.0f; // axis.y *= 100.0f; // axis.z *= 100.0f; // #endif // else { // cerr << "axis(" << axis.x << ", " << axis.y << ", " << axis.z // << ")" << endl; // } vec3_t topvec = {0,1,0}; double lapse; if (cfait->endtime) lapse = cfait->endtime - cfait->startime; else lapse = time - cfait->startime; size_t vtmp1 = RotatedSphereVertex( ptr, VERTEX_ITEMS, xedges, yedges, lapse, topvec, cfait->center); v1 += vtmp1; // cerr << "sphere v1: " << v1 // << ", vtmp: " << vtmp1 // << ", vertices: " << vertices << endl; assert( v1 <= cfait->end_vertex); } break; } } glUnmapBuffer(GL_ARRAY_BUFFER); glBindBuffer( GL_ARRAY_BUFFER, 0); if (vertices) { glBindVertexArray( vertex_array); glBindBuffer( GL_ARRAY_BUFFER, array1); glEnableVertexAttribArray( 0); glVertexAttribPointer( 0, 3, GL_FLOAT,GL_FALSE,VERTEX_ITEMS*sizeof(GLfloat), (const void*)(sizeof(GLfloat)*0)); glEnableVertexAttribArray( 1); glVertexAttribPointer( 1, 4, GL_FLOAT, GL_TRUE,VERTEX_ITEMS*sizeof(GLfloat), (const void*)(sizeof(GLfloat)*3)); glEnableVertexAttribArray( 2); glVertexAttribPointer( 2, 3, GL_FLOAT, GL_TRUE,VERTEX_ITEMS*sizeof(GLfloat), (const void*)(sizeof(GLfloat)*7)); glBindBuffer( GL_ARRAY_BUFFER, 0); glBindVertexArray( 0); } glBindBuffer( GL_ARRAY_BUFFER, array2); glBufferData( GL_ARRAY_BUFFER, vertices*sizeof(GLfloat)*VERTEX_ITEMS, NULL, GL_DYNAMIC_DRAW); GLfloat *ptr2 = (GLfloat*)glMapBufferRange( GL_ARRAY_BUFFER, 0, vertices*sizeof(GLfloat)*VERTEX_ITEMS, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT); { } glUnmapBuffer(GL_ARRAY_BUFFER); glBindBuffer( GL_ARRAY_BUFFER, 0); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, element_array); glBufferData( GL_ELEMENT_ARRAY_BUFFER, elements*sizeof(GLuint), NULL, GL_DYNAMIC_DRAW); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, element_array); size_t e=0; GLuint *eptr = (GLuint*)glMapBufferRange( GL_ELEMENT_ARRAY_BUFFER, 0, elements*sizeof(GLuint), GL_MAP_READ_BIT|GL_MAP_WRITE_BIT); for (list<fireaxis_t>::const_iterator cfait = fireaxes.begin(); cfait != fireaxes.end(); ++cfait) { switch (cfait->firetype) { case fireaxis_t::FIRE_CORN: { GLuint *ptr = &eptr[cfait->element]; size_t index = cfait->vertex; // cerr << "begin rotated corn element." << endl; e += RotatedCornElement( ptr, index, xedges, yedges); // if( ! (e <= elements)) { // cerr << "e: " << e // << ", elements: " << elements << endl; // } assert(e <= cfait->end_element); } break; case fireaxis_t::FIRE_CYLINDER: break; case fireaxis_t::FIRE_SPHERE: { GLuint *ptr = &eptr[cfait->element]; size_t index = cfait->vertex; e += RotatedSphereElement( ptr, index, xedges, yedges); assert(e <= cfait->end_element); } break; } } glUnmapBuffer( GL_ELEMENT_ARRAY_BUFFER); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0); } void fireball_t::Draw( const vec3_t &position, double rate) const{ s_gl_program.Use(); mat4_t mat4 = { {{1,0,0,0}, {0,1,0,0}, {0,0,1,0}, {position.x, position.y, position.z, 1}} }; glUniformMatrix4fv(s_model_location, 1, GL_FALSE, &mat4.row[0].x); glPrimitiveRestartIndex(-1); glEnable(GL_PRIMITIVE_RESTART); glBindVertexArray( vertex_array); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, element_array); // glPointSize(5.0f); glDrawElements( GL_TRIANGLE_STRIP, elements, GL_UNSIGNED_INT, 0); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0); glBindVertexArray( 0); glDisable(GL_PRIMITIVE_RESTART); s_gl_program.Unuse(); } |
#include <windows.h> #include <cmath> #include <iostream> using namespace std; #include <GL/freeglut.h> #include <gl_extloader.h> #include "vec.h" #include "firesub.h" #include "fireball.h" #define MAX_FIREBALLS 128 static bool pause=false; static vec3_t eyedir; static DWORD nowtime, lapse; static fireball_t fireball; static vec3_t positions[MAX_FIREBALLS]; static int fireballnumber = 0; static mat4_t projmtx; static size_t width, height; void idle(); void OnFire( int x, int y, DWORD time) { cerr << "OnFire(" << x << ", " << y << ", " << time << ")" << endl; vec3_t &pos = positions[fireballnumber++]; fireballnumber %= MAX_FIREBALLS; float halfwidth = (width >> 1); float halfheight= (height>> 1); float my = height - 1 - y; pos.x = (x - halfwidth)/halfwidth; pos.y = (my - halfheight)/halfheight; pos.z = -fireball.getCenter().z - 2.0f; // ptr->startime = time; // ptr->position.x = x; // ptr->position.y = y; // ptr->position.z = 0; // ptr->direction = eyedir; } void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); fireball_t::s_gl_program.Use(); glUniformMatrix4fv( fireball_t::s_proj_location, 1, GL_FALSE, &projmtx.row[0].x); fireball_t::s_gl_program.Unuse(); // vec3_t pos = {0,0,-10}; // fireball.Draw(pos, 0.0f); for (int i = 0; i< MAX_FIREBALLS; i++) { fireball.Draw( positions[i], 0.0f); } GLenum errcode = glGetError(); if (errcode) { cerr << "error: " << gluErrorString(errcode) << endl; } #if 0 glMatrixMode(GL_PROJECTION); glLoadMatrixf(&projmtx.row[0].x); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0,0,-10); vec3_t axis1 = { 0,0,1 }; vec3_t axis2 = { 0,0.7071,0.7071 }; mat4_t mat = RotateMatrix( axis1, axis2 ); glMultMatrixf(&mat.row[0].x); glBegin(GL_TRIANGLES); glColor4f(0,0,0.5,1); glVertex3f(0,1,0); glVertex3f(1,0,0); glVertex3f(-1,0,0); glEnd(); #endif glutSwapBuffers(); } void reshape( int w, int h) { glViewport( 0, 0, w, h); width = w; height= h; const double aspect = double(w) / double(h); const double radiangle= 2.0 * M_PI * 90.0 / 360.0; const double mnear = 1.0; const double mfar = 1000.0; double half_length = tan(radiangle*0.5) * mfar; double normal_half_width = aspect; double normal_slash_length = sqrt(normal_half_width*normal_half_width+1.0); double multiply = half_length / normal_slash_length; double half_height = multiply; double half_width = half_height * aspect; double near_rate = mnear / mfar; half_width *= near_rate; half_height*= near_rate; projection_t proj; proj.m_left = -half_width; proj.m_right = half_width; proj.m_bottom = -half_height; proj.m_top = half_height; proj.m_near = 1.0; proj.m_far = 1000.0; projmtx = getPerspectiveMatrix(proj); } void keyboard( unsigned char key, int x, int y) { switch (key) { case 0x1b: //esc key. case 'q': fireball.Destroy(); exit(0); break; case 'p': pause = !pause; if (pause) { glutIdleFunc(NULL); } else { nowtime = timeGetTime(); glutIdleFunc(idle); } break; case 0x0d: {//return(enter) key. // cerr << "pressed return key" << endl; const vec3_t origin = {0,0,0}; fireball.EndBurn(); fireball.Center(origin); fireball.StartBurn(); } break; case 0x20: //space key. OnFire( x, y, timeGetTime() ); break; } } void mouse( int button, int state, int x, int y) { switch (button) { case 0: //fire shot. if (state == 0) { //press. OnFire( x, y, timeGetTime() ); } break; case 1: //. if (state == 0) { //press. } else { //release. } break; case 2: //. if (state == 0) { //press. } else { //release. } break; } } void motion( int x, int y) { } void wheel( int number, int direction, int x, int y) { if (number) return; } void idle() { DWORD newtime = timeGetTime(); lapse = newtime - nowtime; nowtime = newtime; double lapsed = (double)(lapse) * 0.001; // for (int i = 0; i< MAX_FIREBALLS; i++) { // positions[i].x += eyedir.x * lapsed; // positions[i].y += eyedir.y * lapsed; // positions[i].z += eyedir.z * lapsed; // } fireball.Lapse(lapsed); fireball.KeyFrame(); glutPostRedisplay(); } void init( const char *title) { glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH ); glutCreateWindow( title ); glutFullScreen(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMouseFunc(mouse); glutMotionFunc(motion); glutIdleFunc(idle); glutSetKeyRepeat(GLUT_KEY_REPEAT_ON); glutSetCursor(GLUT_CURSOR_CROSSHAIR); gl_extloader_init(); glClearColor(0.18f, 0.18f, 0.18f, 0.0f); glDisable(GL_DITHER); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glEnable(GL_BLEND); glBlendFunc( GL_SRC_ALPHA, GL_ONE ); fireball.Init(); eyedir.x= 0; eyedir.y= 0; eyedir.z= -5; fireball.Operation(eyedir); fireball.StartBurn(); nowtime = timeGetTime(); for (int i = 0; i< MAX_FIREBALLS; i++) { // fireballs[i].startime = nowtime; positions[i].x = (i % 10 - 5) * 2; positions[i].y = (i / 10 - 5) * 2; positions[i].z = -2; // fireballs[i].direction = eyedir; } } int main(int argc, char **argv) { glutInit(&argc, argv); init( argv[0]); glutMainLoop(); return 0; } |
#include行の途中にある「using namespace std;」は、C++標準ライブラリに定義されている名前空間std内にある機能群を、「std::」の指示子無しで利用できるようにするための命令です。
このため、見知らぬ名前を見つけたら、それはstd標準ライブラリ内にある名前かどうかを疑ってください。
ファイルの一番最後ら辺にあるmain関数「int main(int argc, char **argv)」が、プログラムの開始位置になります。
ここからプログラム実行のすべてが始まります。
このように、関数を実装する場合は、返り値型、関数名、括弧内に引き数(型と変数名称)を書くことにより行ないます。
main関数で初期化ルーチンを呼び出していますが、glutInit関数は、描画に使用しているglutの初期化関数です。glutを使用する場合は真っ先に必ず呼び出しましょう。
このように、関数を呼び出す場合は、関数名に括弧を付け、カッコ内に引き数を渡すことで行ないます。
引き数には、変数の受け渡しを行なわせる場合は変数名を、固定値を渡す場合は数値や#defineで行なった定義名を渡します。
変数を受け渡す場合、変数は値渡しになるため普通は呼び出し側の変数を関数内で書き変えることは出来ませんが、&記号を付けることでその変数の位置(メモリアドレス:メモリ番地の値のこと)を渡し、変数の内容書き換えを関数内で行なうことが出来るようにすることも出来ます。
次に自前の初期化関数であるinit関数を呼び出して、OpenGL周りなどの初期化を行なっています。
init関数では、まずglutの初期表示モードを設定、ウィンドウを作成し、フルスクリーンモードにしています。
その次にglutから呼び返されるコールバック関数群、アニメーションに必要なidle関数まで登録しています。
次にキーボードのリピート設定を行ない、スペースキーを押しっ放しにする事によって連打した時と同じ動作になるように設定しています。
次にマウスカーソルを十字に設定、照準代わりです。
その次に、重要なのがgl_extloader_init関数で、OpenGL 1.1を超えるOpenGL関数群を呼び出したい場合に必要となりますので、必ず呼び出してください。
この関数は、OpenGLのコンテキストが必要となりますので、ウィンドウを作ってから呼び出すことが重要です。
さらにOpenGLの初期値を設定し、シーンのレンダリングに備えています。
背景色をglClearColor関数で設定、ディザ(GL_DITHER)、デプステスト(GL_DEPTH_TEST)、背面のカリング(除去, GL_CULL_FACE)をオフ(glDisable)にして取り止め、混合(GL_BLEND)をオンにし, 混合関数(glBlendFunc)を設定しています。
glClearColor関数は、glClear関数にGL_COLOR_BUFFER_BITを渡された場合に塗りつぶす色を、赤、緑、青、不透明度の順に0〜1.0の間で設定することが出来ます。
ちなみに不透明度は、0が透明で、1.0が不透明です。
ディザは、最終的な色値が0〜1.0となる色範囲を、(フレームバッファが32bitsの場合)各色値が整数の0〜255になるので、それを割り当てる際、精度区切りに端数が出た場合に切り上げと切り捨てを交互に行なうことで、見かけ上中間色を表現できるようにするスイッチです。
これをglDisable関数で切り捨てモードにすることにより、グラデーションが綺麗に遷移するようにしています。
ちなみに有効にしたい場合はglEnable関数に定義名を渡せば有効に出来ます。
デプステストは、不透明なモデルを描画する場合に、奥に隠れた面だけを上書きするようにするスイッチで、火は透明で、奥に隠れた火も描画する必要があるので、オフにしています。
背面のカリングは、火は透明であり、表面が裏向いていても描画する必要があるため、オフにしています。
混合は、火は重なるとその分明るくする必要があるためオンにして、混合関数をモデルの不透明度の割合がフレームバッファの色値と加算されるように設定しています。
最後に、自前のfireball_tクラスの変数を初期化しています。
fireball_tクラスのKeyFrameメソッドで形状を計算し結果を利用していますが、これにエフェクトを掛けようとする場合、2種類の方法があります。
その方法とは、fireball_tクラスに移動量を計算させモデルデータに移動量を予め加算しておく方法と、Drawメソッドで行なっているようにOpenGLに行列を渡してモデルを移動させる方法の2種類です。
fireball_tクラスに計算させる方法は、ファイヤーボール自らが移動している効果となり、燃え上がる炎の先端はそのままの位置だけど、中心が移動するように出来ます。
計算結果を移動させる方法は、風が吹いている場合などファイヤーボール全体がそのまま移動させられる場合に利用出来ます。
次に、forループで基準角(z軸+方向が頂点)としてポリゴン座標を計算しています。
スペースキーを押して、ファイヤーを連続発射した所をキャプチャしてみました。
その他、Cヘッダファイル等が参考になります。
c:/msys32/mingw32/i686-w64-mingw32/include/GL/gl.hやglext.h
c:/msys32/mingw32/include/GL/freeglut.h