Jump to content

  • Log In with Google      Sign In   
  • Create Account

#ActualSuen

Posted 29 December 2012 - 10:28 AM

The above was fixed by tweaking some of the values (for now at least). I've hit another problem (unrelated to the topic) but I'm not sure if a whole new thread is needed for that as I've created this thread. Either way I'll give it a try:

I'm trying to render triangles. For the moment I just tried rendering one triangle using a geometric solution (inefficient but but it will have to do for now as I'm just experimenting). I create a triangle consisting of three vertices, then perform a ray-triangle intersection by checking first whether the ray intersects the plane which the triangle lies in and then whether it lies within the triangle or not. The code for this is below along with the code that renders my scene.

The problem I have is that the z-values seem to be flipped when I translate my triangle. If I transform the triangle from it's model space to the world space by a simple translation (no orientation involved) I expect +20 in the z-axis to bring the triangle closer to the camera, yet the result is that my triangle is placed further away from the camera. Using -20 brings the triangle closer to the camera. I thought my matrix transformations might be at wrong here so I specified the coordinates of the triangle's vertices in it's local space (model space) with different z-values to see if I would get the same result and I did.

 

Update: After going through my code again I noticed I was calculating the constant D of the plane equation wrong in my triangle intersection code. It should be D = -(N*V) where N is normal of plane and V is any of the triangle's vertices. I forgot to add the minus sign to it. It works as it should now.
 


#1Suen

Posted 28 December 2012 - 09:13 PM

The above was fixed by tweaking some of the values (for now at least). I've hit another problem (unrelated to the topic) but  I'm not sure if a whole new thread is needed for that as I've created this thread. Either way I'll give it a try:

I'm trying to render triangles. For the moment I just tried rendering one triangle using a geometric solution (inefficient but but it will have to do for now as I'm just experimenting). I create a triangle consisting of three vertices, then perform a ray-triangle intersection by checking first whether the ray intersects the plane which the triangle lies in and then whether it lies within the triangle or not. The code for this is below along with the code that renders my scene.

The problem I have is that the z-values seem to be flipped when I translate my triangle. If I transform the triangle from it's model space to the world space by a simple translation (no orientation involved) I expect +20 in the z-axis to bring the triangle closer to the camera, yet the result is that my triangle is placed further away from the camera. Using -20 brings the triangle closer to the camera. I thought my matrix transformations might be at wrong here so I specified the coordinates of the triangle's vertices in it's local space (model space) with different z-values to see if I would get the same result and I did.

The first image shows the triangle further away from me (20.0 in the vertices z-value). The second image shows it closer to me (-20.0 in the vertices z-value) when it should be the reverse. As far as I'm concerned both the ray and the triangle should be in the same space (ray transformed from raster to world space and object is multiplied by an identity matrix which puts it in world space) so it shouldn't be a problem there. So I'm failing to notice something that should be very obvious or I'm somehow flipping the values somewhere in my code. What could it be?

const int imageWidth = 600;
const int imageHeight = 600;
float aspectR = imageWidth/(float)imageHeight;
float fieldOfView = 50.0f;

Image testImage("image1.ppm", imageWidth, imageHeight);

int main()
{    
    Scene scene1;
    scene1.buildScene();

    std::cout << "Rendering scene..." << std::endl;

    renderScene(scene1);

    std::cout << "Scene rendered" << std::endl;

    return 0;
}

void renderScene(Scene& world)
{
    //Create shader object which is used to shade all objects in the scene
    Shader objectShader(world.lights(), world.nrOfLights());

    //Create a ray with an origin and direction. Origin will act as the
    //CoP (Center of Projection)
    Ray r(glm::vec3(0.0f, 0.0f, 35.0f), glm::vec3(0.0f));

    //Will hold ray (x,y)-direction in world space
    float dirX, dirY;

    //Loop through each pixel...
    for(int y=0; y<imageHeight; y++)
    {
        for(int x=0; x<imageWidth; x++)
        {
            //Normalized pixel coordinates, remapped to range between [-1, 1].
            //Formula for dirY differs because we want to swap the y-axis so
            //that positive y-values of coordinates are on the upper half of
            //the image plane with respect to the center of the plane.
            dirX = (2.0f*(x+0.5f)/imageWidth)-1.0f;
            dirY = 1.0f-(2.0f*(y+0.5f)/imageHeight);

            //Account for aspect ratio and field of view
            dirX = dirX*aspectR*glm::tan(glm::radians(fieldOfView));;
            dirY = dirY*glm::tan(glm::radians(fieldOfView));

            //Set the ray direction in world space. We can calculate the distance
            //from the camera to the image plane by using the FoV and half height
            //of the image plane, tan(fov/2) = a/d => d = a/tan(fov/2)
            r.setDirection(glm::vec3(dirX, dirY, 31.0f)-r.origin());
            
            //Will hold object with closest intersection
            const Object* currentObject = NULL;

            //Will hold solution of ray-object intersection
            float closestHit = std::numeric_limits<float>::infinity(), newHit = std::numeric_limits<float>::infinity();

            //For each object...
            for(int i=0; i<world.nrOfObjects(); i++)
            {
                //If ray intersect object...
                if(world.object(i)->intersection(r, newHit))
                {
                    //If intersection is closer then previous intersection
                    if(newHit<closestHit)
                    {
                        //Update closest intersection and corresponding object
                        closestHit = newHit;
                        currentObject = world.object(i);
                    }
                }
            }

            //If an object has been intersected...
            if(currentObject != NULL)
            {
                //Get intersection point
                glm::vec3 intersectionPoint = r.origin()+closestHit*r.direction();
        
                glm::vec3 RGB = objectShader.diffuse(currentObject, intersectionPoint);

                //Make sure color values are clamped between 0-255 to avoid artifacts
                RGB = glm::clamp(RGB*255.0f, 0.0f, 255.0f);

                //Set color value to pixel
                testImage.setPixel(x, y, RGB);
            }
            else
            {
                //No intersection, set black color to pixel.
                testImage.setPixel(x, y, glm::vec3(0.0f));
            }
        }
    }

    //Write out the image
    testImage.writeImage();
}
Triangle::Triangle()
: m_vertex1(glm::vec3(-1.0f, 0.0f, -20.0f)), m_vertex2(glm::vec3(1.0f, 0.0f, -20.0f)), m_vertex3(glm::vec3(0.0f, 1.0f, -20.0f))
{
    //Calculate edges of triangle
    glm::vec3 edge1 = m_vertex2-m_vertex1;
    glm::vec3 edge2 = m_vertex3-m_vertex1;

    //Take cross product to get normal
    m_normal = glm::normalize(glm::cross(edge1, edge2));
}

bool Triangle::intersection(const Ray &ray, float &ray_t) const
{
    //Get cosine of angle between ray direction and triangle normal
    float NdotRD = glm::dot(m_normal, ray.direction());

    //If the normal and ray direction are perpendicular to each other...
    if(NdotRD == 0)
    {
        //Ray is parallell with the plane which triangle is in
        return false;
    }

    float d = glm::dot(m_normal, m_vertex1);
    float t = -(glm::dot(m_normal, ray.origin())+d)/NdotRD;

    //If solution is negative...
    if(t < 0)
    {
        //Intersection happens behind ray origin, disregard
        return false;
    }

    //Point lies on plane but need to see if point lies within triangle
    //Use geometric approach

    //Intersected point
    glm::vec3 interPoint = ray.origin()+t*ray.direction();
    //Stores one edge of the triangle
    glm::vec3 triEdge;
    //Stores vector from triangle vertex to the intersected point on plane
    glm::vec3 vP;

    //Calculate edge of triangle and vector from vertex to intersected point
    //(v1->v2, v1->vP)
    triEdge = m_vertex2-m_vertex1;
    vP = interPoint-m_vertex1;

    //Get vector perpendicular to triangle edge and vector from vertex
    //to intersected point
    glm::vec3 vPerp = glm::cross(triEdge, vP);

    //If perpendicular vector above has opposite direction of triangle
    //normal then intersected point lie outside triangle with respect
    //to the triangle edge in consideration (in this case edge v1->v2).
    //Repeat for all other triangle edges
    if(glm::dot(m_normal, vPerp) < 0)
    {
        //Outside triangle
        return false;
    }

    //Calculate next edge of triangle and vector to intersected point
    //(v2->v3, v2->vP)
    triEdge = m_vertex3-m_vertex2;
    vP = interPoint-m_vertex2;

    vPerp = glm::cross(triEdge, vP);

    if(glm::dot(m_normal, vPerp) < 0)
    {
        //Outside triangle
        return false;
    }

    //Calculate next edge of triangle and vector to intersected point
    //(v3->v1, v3->vP)
    triEdge = m_vertex1-m_vertex3;
    vP = interPoint-m_vertex3;

    vPerp = glm::cross(triEdge, vP);

    if(glm::dot(m_normal, vPerp) < 0)
    {
        //Outside triangle
        return false;
    }

    ray_t = t;

    //Inside triangle
    return true;
}

 

 


PARTNERS