带光线追踪的圆柱相交

时间:2021-01-04 16:33:47

标签: c raytracing

我是这里的新手,我正在尝试用 C 创建一个光线追踪程序,我正在研究圆柱体形状。
到目前为止,我只有一半的圆柱体,我正在努力寻找获得另一半的方法。
我检查了法线,这似乎不是问题。
我也试图改变无交点的条件,但没有任何效果。
这是我到目前为止所做的:

#include <iostream>
#include <cstring>

//Global Variables
int Temperature=100;
int Heat=100;
int Cool=100;
char Status[100]="Nothing";
char Source[100]="Default";
char gbuffer[900];

struct schedulePoint {
  uint8_t days = 12;
  uint8_t heat = 65;
  uint8_t cool = 85;
  uint16_t start = 60*24;
  uint16_t end = 60*24;
};

struct myData {
  char myName[12] = "TestStat";
  schedulePoint schedule[64];
  char password[25];
  char ssid[25] = "Wifi Thermostat";
  bool hidden = false;
  uint8_t defaultHeat = 65;
  uint8_t defaultCool = 85;
  int timezone = 0;
  char serverUName[25] = "";
  char serverPW[25] = "";
} data;


char * get_JSON(char * buff, unsigned int buffSize) {
  std::cout << "Buffer Size:" << buffSize << "\n";
  char convert[500];
  strcpy(convert,"<script>schedule=[");
  strcpy(buff,convert);
  for (uint8_t z = 0; z < 64; z++) {
    if (z == 0) strcat(buff, "[");
    else strcat(buff, ",[");
    sprintf(convert, "%d,%d,%d,%d,%d]", data.schedule[z].days, data.schedule[z].heat, data.schedule[z].cool, data.schedule[z].start, data.schedule[z].end);
    strcat(buff, convert);
  }
  strcat(buff, "];\n");
  sprintf(convert, "SSID=\"%s\";\n",data.ssid);
  strcat(buff, convert);;
  strcat(buff, "states=[\"Off\",\"Heating\",\"Cooling\"];\n");
  sprintf(convert, "stats={\"Temperature\":%d,\"State\":%s,\"Heat\":%d,\"Cool\":%d,\"Source\":\"%s\"};\n</script>", Temperature, Status, Heat, Cool, Source);
  strcat(buff, convert);
  return buff;
}


int main(){
        char buffer[1000];
        std::cout << get_JSON(gbuffer,sizeof(gbuffer));
        std::cout << "\n";
        std::cout << "Ouput Size:" << (unsigned)strlen(gbuffer);
        std::cout << "\n";
        return 0;
}
t_inter_point ft_cylinder_collision(t_ray ray, t_pack cylinder, int id)
{
    t_inter_point inter_point;
    t_delta delta;
    t_ray new_ray;
    t_vect c_to_o;

    inter_point.hit = FALSE;
    inter_point.id = id;
    new_ray.origin = ray.origin;
    cylinder.rot = normalize(cylinder.rot);
    new_ray.direction = cross(ray.direction, cylinder.rot);
    c_to_o = sub(ray.origin, cylinder.pos);
    delta.a = dot(new_ray.direction, new_ray.direction);
    delta.b = 2 * dot(new_ray.direction, cross(c_to_o, cylinder.rot));
    delta.c = dot(cross(c_to_o, cylinder.rot), cross(c_to_o, cylinder.rot)) - pow(cylinder.diameter / 2, 2);
    delta.delta = pow(delta.b, 2) - 4 * delta.c * delta.a;
    if (delta.delta < 0)
        return (inter_point);
    inter_point.t1 = (-delta.b - sqrt(delta.delta)) / (2 * delta.a);
    inter_point.t2 = (-delta.b + sqrt(delta.delta)) / (2 * delta.a);
    if (inter_point.t2 < 0)
        return (inter_point);
    inter_point.t = (inter_point.t1 > 0 ? inter_point.t1 : inter_point.t2);
    return (ft_find_edges(cylinder, ray, inter_point));
}

The rendered half cylinder

所以问题是:有没有办法用这个方程得到完整的圆柱体? (谢谢)

1 个答案:

答案 0 :(得分:1)

我发现了我的错误,如果将来有人需要这个,我会尝试在这里描述它。 所以基本上,当渲染一个无限圆柱体时,我们尝试获得最近的交点并渲染它。对于我们切割的有限圆柱,它不起作用。 如果交点到圆柱中心的距离大于圆柱的长度,那么我们不考虑交点。即使在最近的交叉点处没有交叉点(太高),在它后面有一个可能在圆柱体高度范围内的交叉点。这是我们需要得到圆柱体另一侧的交点。

也许一些伪代码会有所帮助

// I assume you already found t1 and t2, the two intersections
if (t2 < 0) return ;
t = (t1 > 0 ? t1 : t2);

double max = sqrt(pow(cylinder.height / 2, 2) + pow(cylinder.radius, 2)); //pythagoras theorem
t_vect point = ray.origin + ray.direction * t;
t_vect len = point - cylinder.center;
if (norm(len) > max) // if t1 is too high we try with t2
   t = t2;

t_vect point = ray.origin + ray.direction * t;
len = point - cylinder.center;
if (norm(len) > max) // if t2 is too high too then there is no intersection, else t2 is the intersection. And t2 is in the second half of the cylinder
   return;

如果我可以尝试用一句话来恢复这个,我会说我们首先尝试获得最近的交叉点,但如果它不起作用,我们尝试第二个(与球体不同)。

我希望它在未来对某人有所帮助。 和平(并感谢回答者)