コマンドプロンプトで3Dグラフィック！

# はじめに
初めて書くので、Qiita上で調べて上の方に出てきた
[Qiita Markdown 書き方 まとめ](https://qiita.com/shizuma/items/8616bbe3ebe8ab0b6ca1#%E7%9B%AE%E6%AC%A1)
を参考にしました。ありがとうございます。

ちなみに、私はプログラミング初学者です。（真面目に勉強し始めて2か月くらい）

プログラムを書けると、くだらないことから、真面目なことまで、
できることが広がること、表現の幅が広がると思っています。

あと稼げそう。知らんけど

だからプログラムの勉強をしています。
#### 始まりの言語

c言語は最強だとどこかで聞いた私は、最初の言語にc/c++を選びました
（2つの言語の違いは分かっていません）

プログラムを書くこと自体に慣れるために写経をしていた時、コマンドプロンプトにドーナツを表示させている動画を見付けました。

unityとかDXライブラリとか便利なツールがある中であえて
コマンドプロンプトって最高にロックじゃないですか？

言語の基本は理解しても、どうやって作品を作るかイメージできなかったので、ここまでわかりやすい「なんかすごいプログラム」を見て、これを参考にグラフィックをやってみようと思いました。

__ところで__
径の異なるドーナツを重ねたらどうなると思う？
# うんこをつくりたい！

小学生みたいな発想ですが、参考にして応用できてることが分かりやすくて良くないですか？

ということで、いろいろ参考にしながら１から書いたプログラムの写真がこれ
（無駄な書き方とスペルミスが多いのは今は許して）
![uncode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819223/2717e892-0868-8fd5-0c5b-778b2cde2202.png)

<iframe width="560" height="315" src="https://www.youtube.com/embed/P1PG9B_0Z7M" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

文が間違っているか、計算が遅いせいで、空間がゆがんでいるように見えますね。
（改善の余地ありってコト？！）

やり方は言葉にするとシンプル。

1.ドーナツの各点の座標を計算
2.径と高さを変えて重ねる
3.二次元上に投影した座標を計算
4.コマンドプロンプトに表示
5.コードをうんこ状に成形
__完成__

数学、少しでも勉強しておいて良かったーー

本当は光を当てて、影とかで曲面を表現しようと思っていいたけれど、やらなくてもできることに書いている途中で気づいたのでやめた。（何を引数に表面の柄を決めているか見つけてみてね）

外積などベクトル計算する関数全般を作ることまでせっかくやったので、今度はWindowsアプリケーションでやってみようと思う。

# やってみて気づいた
プログラム書いてて楽しいのは、かけないから。
プログラミングは書くまでがおもしろい
プログラミングは完成した時が楽しい
書く過程をキング・クリムゾンで飛ばしたい。
パラメータ調整はめんどくさい
慣れてもなお、楽しいと感じる仕事やりたいな。（そんなのあるのか）


## ソースコード
動作環境？は
Windows11
Microsoft Visual Studio 2019
c/c++

```
																														#include<math.h> 
																												      # include<stdio.h >
																													   #include<string.h>
																													   #include<stdlib.h>
																													#define WINDOW_HEHGHT (120) 
																													#define WINDOW_WIDTH (350)
																												   #define    DONUT_STEP  ( 4 ) 
																												char buffer[WINDOW_HEHGHT][WINDOW_WIDTH];
																										     int zbuffer[WINDOW_HEHGHT][WINDOW_WIDTH];double K1
																										  = 30.0;double A = 0.5, B = 0.5, C = 0;double dinstance
																										 = 50;double spinSpeed =0.4;typedef struct {double radius,
																										radius_roundZ; double  height;} DONUT; DONUT donuts[DONUT_STEP]
																									   = { {29.0,10.0,0.0},{25.0,10.0,16.0},{19.0,10.0,30.0},{10.0,7.0,
																									    40.0}};double calcurateX(double _rXY, double _rZ, double _rad1
																										,double _rad2) {return ((_rXY + _rZ * cos(_rad2) ) * sin(_rad1
																										  )); } double calcurateY(double _rXY,double _rZ,double _rad1
																									   , double _rad2){return ((_rXY + _rZ * cos(_rad2)) * cos(_rad1));
																									  }double calcurateZ(double _rZ, double _rad2){return _rZ*sin(_rad2)
																								;}double spinX(double i, double j, double k) {return j *  sin(A)  *  sin(B)
																							 * cos(C)- k * cos(A) * sin(B) * cos(C)+ j * cos(A) * sin(C)+ k * sin(A) * sin(C)+
																						    i * cos(B) * cos(C);}double spinY(double i, double j, double k) {return j * cos(A) *
																						   cos(C)+ k * sin(A) * cos(C)- j * sin(A) * sin(B) * sin(C)+ k * cos(A) * sin(B) * sin(C)
																						  - i * cos(B) * sin(C);}double spinZ(double i, double j,double k){return k*cos(A)*cos(B)
																							- j * sin(A) * cos(B)+ i * sin(B);}void createSurface (int  _donutnum , double _x ,
																							  double _y, double _z, double _lightpower) {if (_z == 0)return;double ooz = 1 / _z
																							;int shadow_x =(int)(_x * ooz * K1 + (WINDOW_WIDTH / 2));int shadow_y = (int)(_y*ooz*
																							K1 + (WINDOW_HEHGHT / 2));if ((shadow_x > 0)&& (shadow_x < WINDOW_WIDTH)&& (shadow_y >0)
																						  && (shadow_y < WINDOW_HEHGHT)&&(zbuffer[shadow_y][shadow_y] < ooz)){zbuffer[shadow_y][shadow_y]
																						= (int)ooz;if (((_lightpower <= 100.0) && (_lightpower > 90.0)))buffer[shadow_y][shadow_x] = '@';
																					  else if ( (_lightpower <= 90.0) && (_lightpower > 80.0) ) buffer[shadow_y][shadow_x] = 'a'; else if (
																				    (_lightpower <= 80.0) &&(_lightpower>70.0))buffer[shadow_y][shadow_x] ='*';else if((_lightpower<=70.0) && 
																				 (_lightpower > 60.0))buffer[shadow_y][shadow_x] = '+';else if ((_lightpower <= 60.0) && (_lightpower > 50.0))buffer
																			    [shadow_y][shadow_x] = '=';else if ((_lightpower <= 50.0) && (_lightpower > 40.0))buffer[shadow_y][shadow_x] = '=';
																				else if ((_lightpower <= 40.0) && (_lightpower > 30.0))buffer[shadow_y][shadow_x] = '+';else if ((_lightpower <= 30.0) 
																				&& (_lightpower > 20.0))buffer[shadow_y][shadow_x] = '*';else if ((_lightpower <= 20.0) && (_lightpower > 10.0))buffer
																				[shadow_y][shadow_x] = 'a';else if ((_lightpower <= 10.0) &&(_lightpower > 0.0))buffer[shadow_y][shadow_x] = '@';else 
																				  buffer[shadow_y][shadow_x]=' ';}else return;}void showScreen(){system("cls");for(int y = 0;y < WINDOW_HEHGHT; y++)
																				{for (int x = 0; x < WINDOW_WIDTH; x++) {printf("%c", buffer[y][x]);}printf("\n");}}void Init(){memset(buffer,32,sizeof
																			buffer) ; memset(zbuffer, 0, sizeof zbuffer);}int main() {Init();while (1) {Init();for (int step = 0; step < DONUT_STEP; step++)
																		 for ( double i = 0 ; i < 6.28 ; i +=  0.01 )  for ( double j = 0; j < 6.28 ; j += 0.01 ) {double x = (calcurateX(donuts[step].radius,
																		donuts[step].radius_roundZ , i , j ) ) ; double y = ( calcurateY( donuts[step].radius , donuts[step].radius_roundZ , i , j));double z =
																		calcurateZ(donuts[step].radius_roundZ, j) + donuts[step].height;double afterspinx = spinX(x, y, z);double afterspiny = spinY( x , y , z );
																      double afterspinz = spinZ( x , y , z ) ; createSurface( step , afterspinx , afterspiny , afterspinz +  dinstance , 100 * sin( j < 3.14  ? j :
																	( j - 3.14 ) ) ) ; } showScreen() ; A = ( A < 6.28 ? A += spinSpeed : 0);B=( B < 6.28 ? B += spinSpeed : 0);}return 0;}//Dirty joke save the world
```
巨大すぎる....

#### 衝撃を受けた動画
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/rj7DOPPTkQA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


# 私と同じようなことをやりたいと思った人へ
こんな隅々まで見てくれているということは、やりたいということだろ！？

.........黙っとるちゅうことはYESってことじゃな

下のキーワードで調べ、メモしまくれ！

コンピューターグラフィックス
回転行列（[衝撃を受けた動画](https://youtu.be/rj7DOPPTkQA)でも使われている）

行列
三角関数
球体の座標（立体の座標）

__影つけたいなら__
ベクトル計算
ベクトルの足し算、引き算、内積、外積

で調べるといいと思います。本を利用してもいいと思います。（私はそうしました）

2022/09/23/金曜日　
作成