问题三十六:ray tracing中的Inverse Mapping(2)——凸四边形(含三角形)Inverse Maping

来源:互联网 发布:msn即时软件 编辑:程序博客网 时间:2024/06/09 01:58

36.2 凸四边形(含三角形)Inverse Maping

36.2.1 数学推导

参考“问题三十一”

 

36.2.2 看C++代码实现

----------------------------------------------polygon.cpp ------------------------------------------

polygon.cpp

 

#include "polygon.h"#include "vec2.h"#include "log.h"#include <iostream>#include <fstream>using namespace std;bool in_polygon_test(vec2 *vertexes_uv, int number) {        int sh, nsh;        int nc = 0;        if(vertexes_uv[0].v() < 0) { sh = -1;}        else { sh = 1;}        for(int j=0; j<number; j++) {            if(vertexes_uv[j+1].v() < 0) { nsh = -1;}            else { nsh = 1;}            if(sh != nsh) {                if((vertexes_uv[j].u() > 0) && (vertexes_uv[j+1].u() >0)) { nc++;}                else                    if((vertexes_uv[j].u() > 0) || (vertexes_uv[j+1].u() >0)) {                        if(vertexes_uv[j].u() - (vertexes_uv[j].v())*(vertexes_uv[j+1].u()-vertexes_uv[j].u())/(vertexes_uv[j+1].v()-vertexes_uv[j].v()) > 0) { nc++;}                    }            }            sh = nsh;        }        if((nc)%(2)) {return true;}        else {return false;}}bool in_polygon_test2(vec2 *vertexes_uv, int number) {        int sh, nsh;        int nc = 0;        if(vertexes_uv[0].v() < 0) { sh = -1;}        else { sh = 1;}        for(int j=0; j<number; j++) {            if(vertexes_uv[j+1].v() < 0) { nsh = -1;}            else { nsh = 1;}            if(sh != nsh) {                if((vertexes_uv[j].u() > 0) && (vertexes_uv[j+1].u() >0)) {                    if(vertexes_uv[j].v() > vertexes_uv[j+1].v()) { nc = nc + 1;}                    else { nc = nc - 1;}                }                else                    if((vertexes_uv[j].u() > 0) || (vertexes_uv[j+1].u() >0)) {                        if(vertexes_uv[j].u() - (vertexes_uv[j].v())*(vertexes_uv[j+1].u()-vertexes_uv[j].u())/(vertexes_uv[j+1].v()-vertexes_uv[j].v()) > 0) {                            if(vertexes_uv[j].v() > vertexes_uv[j+1].v()) { nc = nc + 1;}                            else { nc = nc - 1;}                        }                    }            }            sh = nsh;        }        if(nc != 0) {return true;}        else {return false;}}bool polygon::hit(const ray& r, float t_min, float t_max, hit_record& rec) const {        vec3 poly_n;        for(int i=0; i<number-2; i++) {            poly_n = unit_vector(cross((vertexes[i]-vertexes[i+1]), (vertexes[i+1]-vertexes[i+2])));//determine the normal of the plane            if (dot(poly_n, r.direction()) > 0) {                poly_n = - poly_n;            }            if(!vector_equ(poly_n, vec3(0,0,0))) {                break;            }        }        float poly_d = -(dot(poly_n, vertexes[0]));//determine the distance from the origin to the plane        float vd = dot(poly_n, r.direction());        float v0 = -(dot(poly_n, r.origin()) + poly_d);        if(vd == 0) {//the ray is parallel to the polygon plane            return false;        }        else {            float t = v0/vd;//determine t and intersection pi            vec3 pi = r.point_at_parameter(t);            /*find the dominant coordinate, X, Y, or Z?            i=1: means that X is the dominant coordinate;            i=2: means that Y is the dominant coordinate;            i=3: means that Z is the dominant coordinate;            */            float temp = abs(poly_n.x());            int i = 1;            if(temp <= abs(poly_n.y())) {                temp = abs(poly_n.y());                i++;            }            if(temp <= abs(poly_n.z())) {                i++;            }            /*throw the dorminant coordinate of 3-d vector, then we get 2-d vector in uv-plane*/            vec2 vertexes_uv[number+1];            switch (i) {            case 1:                for(int i=0; i<number; i++) {                    vertexes_uv[i] = vec2(vertexes[i].y(),vertexes[i].z());                }                vertexes_uv[number] = vec2(pi.y(),pi.z());                break;            case 2:                for(int i=0; i<number; i++) {                    vertexes_uv[i] = vec2(vertexes[i].x(),vertexes[i].z());                }                vertexes_uv[number] = vec2(pi.x(),pi.z());                break;           case 3:                for(int i=0; i<number; i++) {                    vertexes_uv[i] = vec2(vertexes[i].x(),vertexes[i].y());                }                vertexes_uv[number] = vec2(pi.x(),pi.y());                break;            }            /*move intersection uv-coordinate to origin.            so all the vertexes substract intersection uv-coordinate.*/            for(int i=0; i<number; i++) {                vertexes_uv[i] = vertexes_uv[i] - vertexes_uv[number];            }            vertexes_uv[number] = vertexes_uv[0];            //set the first vertex to the last position of the array, so that we get the whole vertexes loop            if(in_polygon_test2(vertexes_uv,number)) {//check if the intersection locates inside the polygon or not                if (t < t_max && t > t_min) {                    rec.t = t;                    rec.p = r.point_at_parameter(rec.t);                    rec.normal = poly_n;                    rec.mat_ptr = ma;                    if (number <= 4) {                        vec3 p00 = vertexes[0];                        vec3 p10 = vertexes[1];                        vec3 p11 = vertexes[2];                        vec3 p01 = vertexes[0];                        if (number == 4) {                            p01 = vertexes[3];                        }                        vec3 pa = p00-p01+p11-p10;                        vec3 pb = p10-p00;                        vec3 pc = p01-p00;                        vec3 pd = p00;                        vec3 pn = rec.normal;                        vec3 na = cross(pa, pn);                        vec3 nb = cross(pb, pn);                        vec3 nc = cross(pc, pn);                        float du0 = dot(nc, pd);                        float du1 = dot(na, pd) + dot(nc, pb);                        float du2 = dot(na, pb);                        float dv0 = dot(nb, pd);                        float dv1 = dot(na, pd) + dot(nb, pc);                        float dv2 = dot(na, pc);                        vec3 pi = rec.p;                        float Au = du2;                        float Bu = du1 - dot(na, pi);                        float Cu = du0 - dot(nc, pi);                        float Av = dv2;                        float Bv = dv1 - dot(na, pi);                        float Cv = dv0 - dot(nb, pi);                        if (Au == 0) {                            rec.u = -Cu/Bu;                        }                        else {                            float u_temp = (-Bu + sqrt(Bu*Bu-4*Au*Cu)) / (2*Au);                            if ((u_temp >= 0) && (u_temp <= 1)) {                                rec.u = u_temp;                            }                            else {                                rec.u = (-Bu - sqrt(Bu*Bu-4*Au*Cu)) / (2*Au);                            }                        }                        if (Av == 0) {                            rec.v = -Cv/Bv;                        }                        else {                            float v_temp = (-Bv + sqrt(Bv*Bv-4*Av*Cv)) / (2*Av);                            if ((v_temp >= 0) && (v_temp <= 1)) {                                rec.v = v_temp;                            }                            else {                                rec.v = (-Bv - sqrt(Bv*Bv-4*Av*Cv)) / (2*Av);                            }                        }                    }                    return true;                }                 return false;            }            return false;        }}

 

----------------------------------------------main.cpp ------------------------------------------

main.cpp


//triangle        vec3 vertexes3_1[3];        vertexes3_1[0] = vec3(-6.75, 0.0, 0.0);        vertexes3_1[1] = vec3(-4.25, 0.0, 0.0);        vertexes3_1[2] = vec3(-5.25, 2.5, 0.0);//quadrilateral1        vec3 vertexes4_1[4];        vertexes4_1[0] = vec3(-6.5, 3.0 ,0.0);        vertexes4_1[1] = vec3(-1.5, 3.0 ,0.0);        vertexes4_1[2] = vec3(-1.5, 5.5 ,0.0);        vertexes4_1[3] = vec3(-6.5, 5.5 ,0.0);//quadrilateral2        vec3 vertexes4_2[4];        vertexes4_2[0] = vec3(-1.25, 3.0 ,0.0);        vertexes4_2[1] = vec3(3.75, 3.0 ,0.0);        vertexes4_2[2] = vec3(3.0, 5.5 ,0.0);        vertexes4_2[3] = vec3(-0.0, 4.0 ,0.0);        hitable *list[4];        list[0] = new sphere(vec3(0.0,-100,0), 100, new lambertian(vec3(0.8, 0.8, 0.0)));        list[1] = new polygon(vertexes3_1, 3, new lambertian(vec3(0.8, 0.8, 0.0)));        list[2] = new polygon(vertexes4_1, 4, new lambertian(vec3(0.8, 0.8, 0.0)));        list[3] = new polygon(vertexes4_2, 4, new lambertian(vec3(0.8, 0.8, 0.0)));        hitable *world = new hitable_list(list,4);        vec3 lookfrom(0, 2.5, 20);        vec3 lookat(0, 2.5, 0);        float dist_to_focus = (lookfrom - lookat).length();        float aperture = 0.0;        camera cam(lookfrom, lookat, vec3(0,1,0), 20, float(nx)/float(ny), aperture, 0.7*dist_to_focus);

 

输出图片:



uv原图:



4 0
原创粉丝点击