C 三维到二维坐标问题

C 三维到二维坐标问题,c,coordinates,raytracing,C,Coordinates,Raytracing,我正试图从头开始用C语言编写一个非常基本的光线跟踪器。我在从空间中的3d点获取2d坐标时遇到了一些问题 我能够轻松准确地拍摄相机光线,在屏幕上很好地绘制模型。现在我想为屏幕上的模型定义一个边界框,这样我就可以快速移动到与渲染过程无关的图像区域 当物体离相机越近时,我得到的最接近的结果越好。当我把相机向后推(递增cam->pos.z)时,我的边界框开始变得很遥远 我在stackoverflow上看到了十几个不同的公式,我一直在试验/应用这些公式,但都没有成功。如果有人能看看我在做什么,并提供一些建

我正试图从头开始用C语言编写一个非常基本的光线跟踪器。我在从空间中的3d点获取2d坐标时遇到了一些问题

我能够轻松准确地拍摄相机光线,在屏幕上很好地绘制模型。现在我想为屏幕上的模型定义一个边界框,这样我就可以快速移动到与渲染过程无关的图像区域

当物体离相机越近时,我得到的最接近的结果越好。当我把相机向后推(递增cam->pos.z)时,我的边界框开始变得很遥远

我在stackoverflow上看到了十几个不同的公式,我一直在试验/应用这些公式,但都没有成功。如果有人能看看我在做什么,并提供一些建议/纠正,那就太好了

我的坐标是y向上的

我用于获取光线方向的函数(似乎正在工作,但认为可能相关):

三维到二维坐标版本(工作不太好):

编辑:试图利用一些矩阵

    void matrix_projection(double ***m, double fov, 
                 double aspect,double znear, double zfar)
{
    double xymax = znear * tan(fov * M_PI / 360);
    double ymin = -xymax;
    double xmin = -xymax;

    double width = xymax - xmin;
    double height = xymax - ymin;

    double depth = zfar - znear;
    double q = -(zfar + znear) / depth;
    double qn = -2 * (zfar * znear) / depth;

    double w = 2 * znear / width;
    w = w / aspect;

    double h = 2 * znear / height;

    (*m)[0][0]  = w; (*m)[1][0]  = 0; (*m)[2][0]  = 0;   (*m)[3][0] = 0;
    (*m)[0][1]  = 0; (*m)[1][1]  = h; (*m)[2][1]  = 0;   (*m)[3][1] = 0;
    (*m)[0][2]  = 0; (*m)[1][2]  = 0; (*m)[2][2]  = q;   (*m)[3][2] = qn;
    (*m)[0][3]  = 0; (*m)[1][3]  = 0; (*m)[2][3]  = -1;  (*m)[3][3] = 0;
} 
//projection_matrix * modelview_matrix * world_coordinates

void matrix_multiply(double ***result, double ***m1, int r1, 
                        int c1, double ***m2, int c2)
{
    int i, j, k;
    for(i=0; i<r1; ++i)
        for(j=0; j<c2; ++j)
            for(k=0; k<c1; ++k)
            {
                (*result)[i][j] += ((*m1)[i][k]) * ((*m2)[k][j]);
            }
}

void matrix_allocate(double ***matrix, int rows, int cols)
{
    int x, y;
    *matrix = (double**) malloc(sizeof(double *) * rows);
    for (x=0; x < rows; x++) {
        (*matrix)[x] = malloc(sizeof(double) * cols);
        for(y=0; y < cols; y++) {
            (*matrix)[x][y] = 0.0;
    }
}
}

Coordinate coord_fromVector(Vector *v, Vector *cam_pos, int width, int height) {
    Coordinate screen;

    double hwidth = ((double)width) / 2;
    double hheight = ((double)height) / 2;

    double aspect = hwidth / hheight;

    double **proj; 
    matrix_allocate(&proj, 4, 4);
    double **model;
    matrix_allocate(&model, 4, 4);
    double **vmatrix;
    matrix_allocate(&vmatrix, 1, 4);

    vmatrix[0][1] = v->x;
    vmatrix[0][2] = v->y;
    vmatrix[0][3] = v->z;
    vmatrix[0][4] = 1;

    matrix_projection(&proj, 55, aspect, 1.0, 2000.0);

    model[0][0] = model[1][1] = model[2][2] = model[3][3] = 1;
    model[3][0] = cam_pos->x;
    model[3][1] = cam_pos->y;
    model[3][2] = cam_pos->z;

    double **proj_model;
    matrix_allocate(&proj_model, 4, 4);
    matrix_multiply(&proj_model, &proj, 4, 4, &model, 4) ;

    double **proj_model_v;
    matrix_allocate(&proj_model_v, 1, 4);
    matrix_multiply(&proj_model_v, &proj_model, 4, 4, &vmatrix, 1);

    screen.x = proj_model_v[0][0] / proj_model_v[0][3];
    screen.y = proj_model_v[0][1] / proj_model_v[0][3];
    return screen;
}
void matrix_投影(双***m,双视野,
双纵横比、双znear、双zfar)
{
双xymax=znear*tan(视场*M_PI/360);
双ymin=-xymax;
双xmin=-xymax;
双倍宽度=xymax-xmin;
双倍高度=xymax-ymin;
双深度=zfar-znear;
双q=-(zfar+znear)/深度;
双qn=-2*(zfar*znear)/深度;
双w=2*Z线/宽度;
w=w/方面;
双h=2*Z耳/高;
(*m)[0][0]=w;(*m)[1][0]=0;(*m)[2][0]=0;(*m)[3][0]=0;
(*m)[0][1]=0;(*m)[1][1]=h;(*m)[2][1]=0;(*m)[3][1]=0;
(*m)[0][2]=0;(*m)[1][2]=0;(*m)[2][2]=q;(*m)[3][2]=qn;
(*m)[0][3]=0;(*m)[1][3]=0;(*m)[2][3]=1;(*m)[3][3]=0;
} 
//投影矩阵*模型视图矩阵*世界坐标
空矩阵乘以(双***结果,双***m1,整数r1,
内部c1,双***平方米,内部c2)
{
int i,j,k;
对于(i=0;iz;
vmatrix[0][4]=1;
矩阵投影(和proj,55,aspect,1.02000.0);
模型[0][0]=模型[1][1]=模型[2][2]=模型[3][3]=1;
模型[3][0]=凸轮位置->x;
模型[3][1]=凸轮位置->y;
模型[3][2]=凸轮位置->z;
双**项目模型;
矩阵分配(项目模型,4,4);
矩阵乘法(&proj_模型,&proj,4,4,&model,4);
双**项目型号v;
矩阵分配(项目模型v,1,4);
矩阵乘法(&proj_模型v,&proj_模型,4,4,&vmatrix,1);
screen.x=proj_model_v[0][0]/proj_model_v[0][3];
screen.y=proj_model_v[0][1]/proj_model_v[0][3];
返回屏幕;
}

不幸的是,在这一阶段还有很长的路要走。

我建议使用与图形库中使用的方法相同的方法(特别是OpenGL的GLU,它有完善的矩阵构造文档)。它记录下来,你可以算出光线的方向。基本上,光线从
winZ=0
向正
winZ
方向移动。我不知道什么是“三维坐标到二维坐标”应该可以。你是在尝试透视投影吗?是的。或多或少。当我将模型解析到内存中时,我注意到我加载的模型的3d边界框是什么。我希望将它们应用到各自的屏幕坐标,并使用它们跳过图像中不需要渲染/光线跟踪的部分。您是否使用投影矩阵等典型的计算机图形学方法?如果是,请参见。您可以使用那里的
win{X,Y,Z}
方程来帮助您。
model
=模型视图矩阵,
proj
=投影矩阵,
view
是视口信息(整数
(X,Y,宽度,高度)
——通常是
(0,0,窗口宽度,窗口高度)
)。我使用的是你上面看到的。我没有使用OpenGL,是的,我已经看到了所有这些页面。如果我知道如何将这些网站中包含的信息应用到我上面看到的内容,我就不会问这个问题了。
Coordinate coord_fromVector(Vector *v, Vector *cam_pos, int width, int height) {
    Coordinate screen;

    double hwidth = ((double)width) / 2;
    double hheight = ((double)height) / 2;

    double x_3D = v->x - cam_pos->x;
    double y_3D = v->y - cam_pos->y;
    double z_3D = v->z - cam_pos->z;

    screen.x = hwidth + (x_3D / z_3D) * hwidth; 
    screen.y = hheight - (y_3D / z_3D) * hheight;

    /* aspect ratio is commented out as its moving the box off screen */

    /*
    double aspect = screen.resolution.width / screen.resolution.height;
    if (aspect > 1.0) {
        screen.x /= aspect;
    } else {
        screen.y *= aspect;
    }
    */
    return screen;
}
    void matrix_projection(double ***m, double fov, 
                 double aspect,double znear, double zfar)
{
    double xymax = znear * tan(fov * M_PI / 360);
    double ymin = -xymax;
    double xmin = -xymax;

    double width = xymax - xmin;
    double height = xymax - ymin;

    double depth = zfar - znear;
    double q = -(zfar + znear) / depth;
    double qn = -2 * (zfar * znear) / depth;

    double w = 2 * znear / width;
    w = w / aspect;

    double h = 2 * znear / height;

    (*m)[0][0]  = w; (*m)[1][0]  = 0; (*m)[2][0]  = 0;   (*m)[3][0] = 0;
    (*m)[0][1]  = 0; (*m)[1][1]  = h; (*m)[2][1]  = 0;   (*m)[3][1] = 0;
    (*m)[0][2]  = 0; (*m)[1][2]  = 0; (*m)[2][2]  = q;   (*m)[3][2] = qn;
    (*m)[0][3]  = 0; (*m)[1][3]  = 0; (*m)[2][3]  = -1;  (*m)[3][3] = 0;
} 
//projection_matrix * modelview_matrix * world_coordinates

void matrix_multiply(double ***result, double ***m1, int r1, 
                        int c1, double ***m2, int c2)
{
    int i, j, k;
    for(i=0; i<r1; ++i)
        for(j=0; j<c2; ++j)
            for(k=0; k<c1; ++k)
            {
                (*result)[i][j] += ((*m1)[i][k]) * ((*m2)[k][j]);
            }
}

void matrix_allocate(double ***matrix, int rows, int cols)
{
    int x, y;
    *matrix = (double**) malloc(sizeof(double *) * rows);
    for (x=0; x < rows; x++) {
        (*matrix)[x] = malloc(sizeof(double) * cols);
        for(y=0; y < cols; y++) {
            (*matrix)[x][y] = 0.0;
    }
}
}

Coordinate coord_fromVector(Vector *v, Vector *cam_pos, int width, int height) {
    Coordinate screen;

    double hwidth = ((double)width) / 2;
    double hheight = ((double)height) / 2;

    double aspect = hwidth / hheight;

    double **proj; 
    matrix_allocate(&proj, 4, 4);
    double **model;
    matrix_allocate(&model, 4, 4);
    double **vmatrix;
    matrix_allocate(&vmatrix, 1, 4);

    vmatrix[0][1] = v->x;
    vmatrix[0][2] = v->y;
    vmatrix[0][3] = v->z;
    vmatrix[0][4] = 1;

    matrix_projection(&proj, 55, aspect, 1.0, 2000.0);

    model[0][0] = model[1][1] = model[2][2] = model[3][3] = 1;
    model[3][0] = cam_pos->x;
    model[3][1] = cam_pos->y;
    model[3][2] = cam_pos->z;

    double **proj_model;
    matrix_allocate(&proj_model, 4, 4);
    matrix_multiply(&proj_model, &proj, 4, 4, &model, 4) ;

    double **proj_model_v;
    matrix_allocate(&proj_model_v, 1, 4);
    matrix_multiply(&proj_model_v, &proj_model, 4, 4, &vmatrix, 1);

    screen.x = proj_model_v[0][0] / proj_model_v[0][3];
    screen.y = proj_model_v[0][1] / proj_model_v[0][3];
    return screen;
}