コード:
#include <math.h>
#include "3d.h"
#if 1
#define DEBUG
#endif
#ifdef DEBUG
#include <stdio.h>
FILE* fpdebug=NULL;
void _debuginit(void) {
fpdebug=fopen("debug.txt","a");
}
void _debugend(void) {
fclose(fpdebug);
fpdebug=NULL;
}
void _printstr(const char* str) {
if(fpdebug==NULL)return;
fprintf(fpdebug,"%s\n",str);
}
void _printbekutoru(const char* exp,double x,double y,double z) {
if(fpdebug==NULL)return;
fprintf(fpdebug,"%s=(%f,%f,%f)\n",exp,x,y,z);
}
void _printnum(const char* exp,double num) {
if(fpdebug==NULL)return;
fprintf(fpdebug,"%s=%f\n",exp,num);
}
#define debuginit _debuginit()
#define debugend _debugend()
#define printstr(s) _printstr(s)
#define printbekutoru(e,x,y,z) _printbekutoru(e,x,y,z)
#define printnum(e,n) _printnum(e,n)
#else
#define debuginit
#define debugend
#define printstr(s)
#define printbekutoru(e,x,y,z)
#define printnum(e,n)
#endif
// マトリクスの設定
void setMatrix( double matrix[][4],
double mat00, double mat01, double mat02, double mat03,
double mat10, double mat11, double mat12, double mat13,
double mat20, double mat21, double mat22, double mat23,
double mat30, double mat31, double mat32, double mat33 )
{
matrix[0][0]=mat00; matrix[0][1]=mat01; matrix[0][2]=mat02; matrix[0][3]=mat03;
matrix[1][0]=mat10; matrix[1][1]=mat11; matrix[1][2]=mat12; matrix[1][3]=mat13;
matrix[2][0]=mat20; matrix[2][1]=mat21; matrix[2][2]=mat22; matrix[2][3]=mat23;
matrix[3][0]=mat30; matrix[3][1]=mat31; matrix[3][2]=mat32; matrix[3][3]=mat33;
}
// マトリックス・ポイント計算
void calcMatrixPoint( double matrix[][4],double out[],double in[])
{
int i,j;
// 行列の演算。
for( i=0 ; i<4; i++ ) {
out[i] = 0;
for( j=0 ; j<4; j++ ) {
out[i] += in[j] * matrix[j][i];
}
}
}
// コピーマトリックス
void copyMatrix( double dstMat[][4],double srcMat[][4])
{
int i,j;
// コピー
for( i=0 ; i<4; i++ ) {
for( j=0 ; j<4; j++ ) {
dstMat[i][j] = srcMat[i][j];
}
}
}
// マトリックス計算
void calcMatrix( double dstMat[][4],double srcMat[][4])
{
int i,j,k;
double matrix[4][4];
// クリア
for( i=0 ; i<4; i++ ) {
for( j=0 ; j<4; j++ ) {
matrix[i][j] = 0;
}
}
// 行列の演算。
for( i=0 ; i<4; i++ ) {
for( j=0 ; j<4; j++ ) {
for( k=0 ; k<4; k++ ) {
matrix[i][j] += dstMat[i][k] * srcMat[k][j];
}
}
}
// コピー
copyMatrix(dstMat,matrix);
}
int henkan3dzahyou(double* ox,double* oy,
double x,double y,double z,const camera_t* camera)
{
double Mmatrix[4][4];//移動変換行列
double Pmatrix[4][4];//射影変換行列
double point3D[4]; //変換前座標
double Mpoint3D[4]; //移動変換後座標
double Ppoint3D[4]; //射影変換後座標
int i,j;
// 3D座標値を設定する。
point3D[0] = x;
point3D[1] = y;
point3D[2] = z;
point3D[3] = 1;
// カメラビュー変換。
{
double Umatrix[4][4];//単位行列
double RXmatrix[4][4];//X回転行列
double RYmatrix[4][4];//Y回転行列
double RZmatrix[4][4];//Z回転行列
// 単位マトリックス
setMatrix( Umatrix,
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1 );
// X回転マトリックス
setMatrix( RXmatrix,
1, 0, 0, 0,
0, cos(camera->cx), sin(camera->cx), 0,
0, -sin(camera->cx), cos(camera->cx), 0,
0, 0, 0, 1 );
// Y回転マトリックス
setMatrix( RYmatrix,
cos(camera->cy),0, -sin(camera->cy), 0,
0, 1, 0, 0,
sin(camera->cy),0, cos(camera->cy), 0,
0, 0, 0, 1 );
// Z回転マトリックス
setMatrix( RZmatrix,
cos(camera->cz),sin(camera->cz), 0, 0,
-sin(camera->cz),cos(camera->cz), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1 );
// 平行移動マトリックス
setMatrix( Mmatrix,
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
camera->x, camera->y, camera->z, 1 );
// マトリックスの合成
calcMatrix(Umatrix,RXmatrix);
calcMatrix(Umatrix,RYmatrix);
calcMatrix(Umatrix,RZmatrix);
calcMatrix(Umatrix,Mmatrix);
copyMatrix(Mmatrix,Umatrix);
}
// 行列の演算。
calcMatrixPoint(Mmatrix,Mpoint3D,point3D);
// 射影変換行列を設定する。
{
double depth,ctan;
double cnear,cfar,width,height;
cnear = 0.1;
cfar = 1000.0;
ctan = tan(camera->genkaiangle*0.5);
width = 1.0 / ctan;
height = 1.0 / ctan;
depth = cfar / (cfar - cnear);
setMatrix( Pmatrix,
width, 0, 0, 0,
0, height, 0, 0,
0, 0, depth, 1,
0, 0, -depth * cnear, 0 );
}
// 行列の演算。
calcMatrixPoint(Pmatrix,Ppoint3D,Mpoint3D);
// スクリーン座標変換。アスペクトは1:1
*ox = camera->centery * Ppoint3D[0] / Ppoint3D[2] + camera->centerx;
*oy = camera->centery * Ppoint3D[1] / Ppoint3D[2] + camera->centery;
return 1;
}
int draw3dline(HDC hdc,double x1,double y1,double z1,
double x2,double y2,double z2,const camera_t* camera,char *info) {
double hx1,hy1,hx2,hy2;
y1 -= 300;
y2 -= 300;
z1 += 200;
z2 += 200;
if(!henkan3dzahyou(&hx1,&hy1,x1,y1,z1,camera))return 0;
if(!henkan3dzahyou(&hx2,&hy2,x2,y2,z2,camera))return 0;
if(!MoveToEx(hdc,(int)hx1,(int)hy1,NULL))return 0;
if(!LineTo(hdc,(int)hx2,(int)hy2))return 0;
if( info != NULL ) {
wsprintf(info,"ライン座標(%d,%d)-(%d,%d)",(int)hx1,(int)hy1,(int)hx2,(int)hy2);
}
return 1;
}