Почему мое изображение с трассировкой лучей полностью черное?

Мне пришлось сгенерировать изображение в виде черного круга, черного (0, 0, 0) и белого (1, 1, 1), но я продолжаю получать полностью черное изображение. Вот весь мой код:

#include "cast.h"
#include "collisions.h"
#include <stdio.h>
#include "math.h"

int cast_ray(struct ray r, struct sphere spheres[], int num_spheres)
{
   int isFound;
   struct maybe_point mp;
   isFound = 0;

   for (int i = 0; i < num_spheres; i++)
   {
      mp = sphere_intersection_point(r, spheres[i]);

      if (mp.isPoint == 1)
      {
         isFound = 1;
      }
      else
      {
         isFound = 0;
      }
   }
   return isFound;
}

void print_pixel(double a, double b, double c)
{
   int i, j, k;

   i = a * 255;
   j = b * 255;
   k = c * 255;

   printf("%d %d %d ", i, j, k);
}

void cast_all_rays(double min_x, double max_x, double min_y, double max_y,
                  int width, int height, struct point eye,
                  struct sphere spheres[], int num_spheres)
{
   double width_interval, height_interval, y, x;
   int intersect;

   width_interval = (max_x - min_x)/width;
   height_interval = (max_y - min_y)/height;

   for (y = max_y; y > min_y; y = y - height_interval)
   {
      for (x = min_x; x < max_x; x = x + width_interval)
      {
         struct ray r;
         r.p = eye;
         r.dir.x = x;
         r.dir.y = y;
         r.dir.z = 0.0;

         intersect = cast_ray(r, spheres, num_spheres);

            if (intersect != 0)
            {
               print_pixel (0, 0, 0);
            }
            else
            {
               print_pixel (1, 1, 1);
            }
      }

У меня уже были заведомо правильные функции, которые определяют, пересекается ли луч со сферой. Функция, которую я использовал для поиска точек пересечения, была в функции cast_ray.

    sphere_intersection_point(r, spheres[i]);

Функция print_pixel преобразует целочисленные значения, умножая их на максимальное значение цвета, равное 255.

А функция cast_all_rays отбрасывает лучи на всю сцену от наших глаз (перебирая все координаты x перед изменением y). Если луч пересекается со сферой, пиксель черный, таким образом, в конце образуется черный круг.

А вот ограничения для x, y и радиуса (ПРИМЕЧАНИЕ: Я ИСПОЛЬЗУЮ ФОРМАТ PPM):

Eye at <0.0, 0.0, -14.0>.
A sphere at <1.0, 1.0, 0.0> with radius 2.0.
A sphere at <0.5, 1.5, -3.0> with radius 0.5.
min_x at -10, max_x at 10, min_y of -7.5, max_y at 7.5, width=1024, and height=768.

Мне нужно сгенерировать изображение черного круга, но я продолжаю получать полностью черное изображение. У меня есть ощущение, что проблема заключается в функции cast_all_rays, но я просто не могу найти, в чем она заключается. Помощь приветствуется! Спасибо.

И на случай, если что-то пойдет не так с моим тестированием, вот мой файл test.c для cast_all_rays:

#include "collisions.h"
#include "data.h"
#include "cast.h"
#include <stdio.h>

void cast_all_rays_tests(void)
{
   printf("P3\n");
   printf("%d %d\n", 1024, 768);
   printf("255\n");

   double min_x, max_x, min_y, max_y;
   int width, height;
   struct point eye;
   struct sphere spheres[2];

   eye.x = 0.0;
   eye.y = 0.0;
   eye.z = -14.0;
   spheres[0].center.x = 1.0;
   spheres[0].center.y = 1.0;
   spheres[0].center.z = 0.0;
   spheres[0].radius = 2.0;
   spheres[1].center.x = 0.5;
   spheres[1].center.y = 1.5;
   spheres[1].center.z = -3.0;
   spheres[1].radius = 0.5;
   min_x = -10;
   max_x = 10;
   min_y = -7.5;
   max_y = 7.5;

   cast_all_rays(min_x, max_x, min_y, max_y, width, height, eye, spheres, num_spheres);
}

int main()

{
   cast_all_rays_tests();

   return 0;
}

person Karen    schedule 17.05.2013    source источник


Ответы (1)


Не уверен, что это проблема, с которой вы столкнулись, но вы должны установить isFound только в том случае, если вы пересекаете сферу. Не устанавливайте его, если вы не пересекаетесь. В противном случае вашим изображением будет управлять только последняя сфера в списке.

  if (mp.isPoint == 1)
  {
     isFound = 1;
  }
  //else
  //{
  //   isFound = 0;
  //}

Поскольку ваше изображение полностью черное, кажется, что ваш код пересечения не работает или ваше поле зрения слишком узкое. Если вам не нравятся вышеупомянутые изменения, возможно, вам следует опубликовать подробности о ваших x- и y-пределах, положении глаз, а также положении и радиусе сферы.

Еще одна вещь, которую я заметил, это r.dir.z = 0.0. Вы вычитаете из этого положение глаз, чтобы получить направление, или это ваше истинное направление луча? Конечно, вам нужно указать ненулевое z-направление. Обычно вы устанавливаете x и y на основе вашей плоскости обзора и предоставляете константу z, такую ​​как 1 или -1.

[править]

Чтобы было понятнее из комментариев ниже, я считаю, что вы неправильно настроили направление луча. Вместо этого вы просто устанавливаете направление как положение пикселя плоскости обзора, игнорируя положение глаза. Следующее было бы более обычным:

     struct ray r;
     r.p = eye;
     r.dir.x = x - eye.x;
     r.dir.y = y - eye.y;
     r.dir.z = 0.0 - eye.z;
person paddy    schedule 17.05.2013
comment
Да, изображение все еще черное. :( Я опубликую ограничения выше. - person Karen; 17.05.2013
comment
Хм... о! В нем говорится, что границы прямоугольника просмотра равны min_x, max_x, min_y и max_y (координата z равна 0). Подождите минутку, так что координата z, на которую они ссылаются, на самом деле НЕ ЯВЛЯЕТСЯ координатой z направления луча? - person Karen; 17.05.2013
comment
Трудно сказать, не видя код пересечения вашей сферы. Мне кажется, что если плоскость обзора центрирована на z=0, вам следует создать луч, направление которого равно положению вашего пикселя в плоскости обзора минус положение глаза. Так что это даст вам z-направление 14. Если вы используете направление луча дословно из того, что я вижу в вашем коде, это будет луч, который вылетает из положения глаза в 2D-круге вокруг точки глаза, а не чем трехмерная усеченная пирамида. Правильно установите направление луча, и все должно быть хорошо. - person paddy; 17.05.2013
comment
Спасибо! Быстрый вопрос, должен ли я вызывать функцию cast_all_rays в своем коде в test.c? Я продолжаю получать сообщение об ошибке: неопределенная ссылка на cast_all_rays. Но если я попытаюсь скомпилировать без вызова функции, ошибок не возникнет. - person Karen; 17.05.2013
comment
Предположительно, один из ваших заголовков (cast.h?) объявляет функцию cast_all_rays. Вы должны использовать extern void cast_all_rays(...); в заголовке. Здесь я использовал ..., но на самом деле вам нужен список параметров со всеми типами. Или это может быть ошибка компоновщика, что означает, что вам нужно связать весь ваш скомпилированный объектный код в один исполняемый файл. Возможно, это лучше объясняет, что ваше изображение полностью черное — если вы не можете собрать свой исходный код, вы должны использовать старую версию. - person paddy; 17.05.2013
comment
давайте продолжим это обсуждение в чате - person Karen; 18.05.2013