C++ Raytracer - Only one object appearing in scene

188 views Asked by At

I am using a raytracer to render a Sphereflake, but I am having trouble trying to have more than object appear in the scene. In the scene below I am just trying to test out having two spheres in a scene, but for some reason only ever one sphere appears in the scene, and usually its the sphere with the largest radius.

Another peculiar thing is, even though there is a camera set in the scene, it seems as though the output window always shows the predominant object at the centre ((0,0) with screen coordinates between [-1,-1]->[1,1]) rather than in relevance to the camera coordinate space.

I am unsure if it is a parent hierarchy problem or how I'm rendering the objects, but any insight into why the problem is persisting would be greatly appreciated.

main.cpp (creates scenes renders objects)

#include <stdio.h>
#include <iostream>
#include <vector>
#include <math.h>
#include <glm.hpp>
#include <gtc/matrix_transform.hpp> 

#include <Raytracer/Raytracer.h>

using namespace glm;
using namespace Raytracer;
using namespace Raytracer::Scenes;
using namespace Raytracer::Objects;

/**
 * Places a few spheres in the scene and adds some lights.
 *
 * @param scene The scene
 */
Scene *BuildScene(int depth, float aspect)
{
    const int materialCount = 6;

    vec3 colors[materialCount] =
    {
      vec3(1.0f, 0.0f, 0.0f),
      vec3(1.0f, 1.0f, 0.0f),
      vec3(0.0f, 1.0f, 0.0f),
      vec3(0.0f, 1.0f, 1.0f),
      vec3(0.0f, 0.0f, 1.0f),
      vec3(1.0f, 0.0f, 1.0f)
    };

    Material *materials[materialCount];

    for (int i = 0; i < materialCount; i++)
    {
        materials[i] = new Material();
        if (materials[i] == NULL)
            return NULL;

        vec3 ambient = colors[i] * 0.01f;
        materials[i]->SetAmbient(ambient);
        materials[i]->SetDiffuse(colors[i]);
        materials[i]->SetShininess(25.0f);
    }

    if (depth <= 0)
        return NULL;

    // Create the scene.
    Scene *scene = new Scene();
    if (scene == NULL)
        return NULL;

    Sphere * s1 = new Sphere(0.33f, materials[5]);
    s1->SetPosition(vec3(5.0f, 0.0f, -2.0f));
    Sphere * s2 = new Sphere(0.33f, materials[1]);
    s2->SetPosition(vec3((5.0f, 0.33f, -2.0f));

    s1->AddChild(s2);

  // Create a light.
  Light *light = new PointLight(vec3(10.0f));
  if (light == NULL)
  {
    delete scene;
    return NULL;
  }

  light->SetPosition(vec3(-5.0f, 3.0f, 2.0f));
  scene->AddChild(light);

  // Create a camera.
  Camera *camera = new Camera(vec3(-2.0f, 2.0f, 4.0f), vec3(0.0f, 0.0f, 0.0f), 
    vec3(0.0f, 1.0f, 0.0f), Camera::DefaultFov, aspect);

  scene->AddChild(s1);

  if (camera == NULL)
  {
    delete scene;
    return NULL;
  }
  scene->AddChild(camera);
  scene->SetActiveCamera(camera);

  return scene;
}

/**
 * Renders the scene and saves the result to a BMP file.
 *
 * @param fileName The name of the file
 * @param width The image width
 * @param height The image height
 */
void Render(const char *fileName, int width, int height)
{
  if (fileName == NULL || width <= 0 || height <= 0)
    return;

  SimpleRenderer renderer;

  renderer.SetAccelerator(new SimpleAccelerator());
  renderer.SetIntegrator(new PhongIntegrator());

  puts("Generiere Szene...");
  Scene *scene = BuildScene(3, (float)width / height);
  if (scene == NULL)
    return;

  puts("Rendere Bild...");
  Image *image = renderer.Render(*scene, width, height);
  if (image != NULL)
  {
    puts("Speichere Ergebnis...");
    image->SaveBMP(fileName, 2.2f);
    delete image;
  }

  delete scene;
}

/**
 * The main program
 */
int main()
{
  Render("image.bmp", 512, 512);
  return 0;
}

example of a scene with two spheres as stated above with s1.radius = 0.33f & s2.radius = 0.33f

scene 1

another example of a scene with two spheres with s1.radius = 0.33f & s2.radius = 1.0f

scene 2

As you can see, it seems the camera is invalid as a point of perspective, as no matter what the position of the sphere is, the only difference is its lighting, but it will always be at the centre of the display window

2

There are 2 answers

3
AudioBubble On BEST ANSWER

Since s2 is attached as a child of s1, it's being drawn 5 units further down the X axis than s1:

s2->SetPosition(vec3((5.0f, 0.33f, -2.0f));
...
s1->AddChild(s2);

And since your camera is looking down the positive x axis:

Camera *camera = new Camera(vec3(-2.0f, 2.0f, 4.0f), 
    vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f), Camera::DefaultFov, aspect);

s2 is simply being drawn behind s1.

0
J.Doe On

It turns out it was not a problem with my scene builder, but how the child/parent inherritance works in another class SceneObject*. Anyway, I fixed the AddChild function and now the code now works with the camera perspective and with mulitple items in the scene