Jump to content


Java Raytracer Problem


6 replies to this topic

#1 appleGuy

    New Member

  • Members
  • PipPip
  • 25 posts

Posted 09 July 2007 - 01:39 PM

Hi,
Im currently trying to make a very simple raytracer. Now ive got this big problem. As shown in the image below the image output is incorrect, however this only happens when I use view plane dimensions that are not the same. (100 x 100 works but 800 x 600 gives the strange output). This has been bugging me for days and I wonder if anyone can spot where ive gone wrong.

Ill include the camera ray spawn code and the render code, minus the intersection code as I know this is correct. Ill also include the tga file creator as that might be the problem.

Thanks for your help
-Alex

render code (inc ray camera spawn):
public void spawnCameraRays(int imageDimX, int imageDimY){

        _raySpawnTable = new Vector3f[imageDimX][imageDimY];

        _cameraPos = new Vector3f();

        

        //Vars to hold half screen width and height

	float halfWidth = (float)imageDimX / 2;

	float halfHeight = (float)imageDimY / 2;

 

	//loop through every pixel and generate ray directions

 

	for(int y = 0; y < imageDimY; y++){

 

		for(int x = 0; x < imageDimX; x++){

                    _raySpawnTable[x][y] = new Vector3f(x - halfWidth, y - halfHeight, 255);

                    _raySpawnTable[x][y].normalize();

                }                

	}

        //Assign member variables the dimensions for memory clean up

        _cleanX = imageDimX;

        _cleanY = imageDimY;

    }

    

    public void cameraRayClean(){

       //Drop hint to GC to clean memory 

       for(int y = 0; y < _cleanY; y++){

           for(int x = 0; x < _cleanX; x++)

               _raySpawnTable[x][y] = null;        

	}

       _raySpawnTable = null;

    }

    

    public boolean traceScene(primitiveObjects.p_sphere obj, viewPlane vPlane, int vpX, int vpY){ // Change when Scene Inc

       //Camera Ray;

        ray cameraRay = new ray();

        cameraRay.setOrigin(new Vector3f(0.0f, 0.0f, -600.0f));

        

        //Loop through all pixels in view plane and trace the cameraRay, based on raySpawnTable;

        if (_raySpawnTable == null || vPlane == null)

            return false;

       

        

        for (int iterX = 0; iterX < vpX; iterX++){

            int rgb = 0; //Loop Iterator for 3 rgb colours

            for(int iterY = 0; iterY < vpY; iterY++, rgb+=3){

                cameraRay.setDirection(_raySpawnTable[iterX][iterY]);

                

                rayTraceResult result;

                result = obj.calcIntersection(cameraRay);

        

                if(result.getHit() == true){

                    vPlane._viewPlane[iterX][rgb + 0] = obj._r;

                    vPlane._viewPlane[iterX][rgb + 1] = obj._g;

                    vPlane._viewPlane[iterX][rgb + 2] = obj._b;

                    //System.out.print("111");

                }

                else{

                    vPlane._viewPlane[iterX][rgb + 0] = 111;

                    vPlane._viewPlane[iterX][rgb + 1] = 111; //RGB Black (More Elegant?)

                    vPlane._viewPlane[iterX][rgb + 2] = 111;

                    //System.out.print("000");

                }

            }

            //System.out.println("");

        }

        

        return true;

    }

    

    //Variables

    private Vector3f _raySpawnTable[][];

    private Vector3f _cameraPos;

Tga out put code:
public boolean writeTGA(String fileName, viewPlane vPlane){

        char tgaHeader[] = {0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0};

	char header[] = new char [6];

	char bits = 24;

        

        int colourMode = 3;

        

        header[0] = (char)(vPlane.getVPlaneX() % 256);

	header[1] = (char)(vPlane.getVPlaneX() / 256);

	header[2] = (char)(vPlane.getVPlaneY() % 256);

	header[3] = (char)(vPlane.getVPlaneY() / 256);

	header[4] = bits;

	header[5] = 0;

        

        try{

            tgaOutFile = new File(fileName);

            tgaOutFile.createNewFile();

        }

        catch(IOException e){

            //EXCEPTION HERE

            System.out.println("Error Creating File");

        }

        

        

        try{

            tgaOutStream = new FileOutputStream(fileName);  

        }

        catch(FileNotFoundException e){

            System.out.println("");

            System.out.println("Error Opening File");

            //EXCEPTION HERE

        }

        

        try{

            for(int i = 0; i < 12; i++)

                tgaOutStream.write(tgaHeader[i]);

            for(int i = 0; i < 6; i++)

                tgaOutStream.write(header[i]);

            

            //Switch RGB -> BGR

            for (int iterX = 0; iterX < vPlane.getVPlaneX(); iterX++){

                for(int iterY = 0; iterY < (vPlane.getVPlaneY() * 3); iterY+=colourMode){

                    char tempColour = vPlane._viewPlane[iterX][iterY];

                    vPlane._viewPlane[iterX][iterY] = vPlane._viewPlane[iterX][iterY + 2];

                    vPlane._viewPlane[iterX][iterY + 2] = tempColour;

                }

            }

            

            //Write Data Image To File

            

            for (int iterX = 0; iterX < vPlane.getVPlaneX(); iterX++){

                for(int iterY = 0; iterY < vPlane.getVPlaneY() * 3; iterY++){

                        tgaOutStream.write(vPlane._viewPlane[iterX][iterY]);

                }

        }

            

            tgaOutStream.close(); //Give Resource Back to VM

        }

        

        catch(IOException e){

            //EXCEPTION HERE

            System.out.println("Error Closing or writing File");

        }

        

        return true;

    }

    

    private FileOutputStream tgaOutStream;

    private File tgaOutFile;

the strange output as unequal resolutions:
http://img.photobuck...ytraceError.jpg

Thanks Again!

#2 flux00

    Valued Member

  • Members
  • PipPipPip
  • 108 posts

Posted 09 July 2007 - 02:31 PM

Hmm, can you describe the format for the viewPlane class? Are you using an int[width][3*height]? Typically ray tracers use three floats to represent red green and blue, and it may be simpler to use a int[width][height][3], or simply color[width][height]. What color range are you using? 0-255?

I'm not familliar with TGA format, but for debugging purposes you could possibly write to a java.awt.Image via java.awt.image.BufferedImage or something along those lines, then just use ImageIO.save(...). If you try that make sure to negate the yY component.

#3 appleGuy

    New Member

  • Members
  • PipPip
  • 25 posts

Posted 09 July 2007 - 03:00 PM

flux00 said:

Hmm, can you describe the format for the viewPlane class? Are you using an int[width][3*height]? Typically ray tracers use three floats to represent red green and blue, and it may be simpler to use a int[width][height][3], or simply color[width][height]. What color range are you using? 0-255?

I'm not familliar with TGA format, but for debugging purposes you could possibly write to a java.awt.Image via java.awt.image.BufferedImage or something along those lines, then just use ImageIO.save(...). If you try that make sure to negate the yY component.

The Code for my viewPlane Class:
package raytracer;


public class viewPlane {

    

    /** Creates a new instance of viewPlane */

    public viewPlane(int dimensionX, int dimensionY) {

        _dimensionX = dimensionX;

        _dimensionY = dimensionY;

    }

    

    public void createViewPlane(){

        //INSERT EXCEPTION

        if(_dimensionX < 1 || _dimensionY < 1){

            //THROW Exception

            ;

        }

        else{

            // _dY * 3 for RGB

            

                _viewPlane = new char [_dimensionX][(_dimensionY * 3)]; 

        }

    }

    

    public void deleteViewPlane(){

        //Drop Hint to Garbage Collector

        _viewPlane = null;

    }

    

    public int getVPlaneX(){

        return _dimensionX; 

    }

    public int getVPlaneY(){

        return _dimensionY;

    }

    

    //Variables

    private int _dimensionX;

    private int _dimensionY;

    public char _viewPlane[][];

    

}

im using a char [image width][image height * 3]. using colour range of 0 -255 hence the type char.

Thanks For Your Help
-Alex

#4 z80

    Valued Member

  • Members
  • PipPipPip
  • 104 posts

Posted 09 July 2007 - 04:19 PM

Hmm.. Ok.. When you are generating your TGA header you treat the X-axis as width and the Y-axis as height, but when you actually write the pixels (at your "Write Data Image To File"-comment) you do it the other way round.

When you write pixels you have to start with the bottom scanline and write pixels from left to right (every pixel should be written as 3 bytes for Blue, Green and Red). You are not doing that right now.

You probably need to make your X-axis in the view buffer 3 times wider instead of the Y-axis. Or perhaps skip the viewPlane alltogether and write the pixels as you trace them (but then of course you have to trace pixels in the correct order, so they will come out right in the file -- you will need the Y-axis as the outmost for-statement in the trace loops). I would avoid creating a big buffer if its not really needed, but that is up to you.

#5 appleGuy

    New Member

  • Members
  • PipPip
  • 25 posts

Posted 09 July 2007 - 04:26 PM

z80 said:

Hmm.. Ok.. When you are generating your TGA header you treat the X-axis as width and the Y-axis as height, but when you actually write the pixels (at your "Write Data Image To File"-comment) you do it the other way round.

When you write pixels you have to start with the bottom scanline and write pixels from left to right (every pixel should be written as 3 bytes for Blue, Green and Red). You are not doing that right now.

You probably need to make your X-axis in the view buffer 3 times wider instead of the Y-axis. Or perhaps skip the viewPlane alltogether and write the pixels as you trace them (but then of course you have to trace pixels in the correct order, so they will come out right in the file). I would avoid creating a big buffer if its not really needed, but that is up to you.

Hi,

Im not sure im with your. Why would making the X axis 3 times bigger than the Y axis make any difference? Surely you are just making room for the RGB values....

Im alittle confussed...

Could you explain abit more please?

Sorry about this
-Alex

Edit:
So in a tga file, the standard is the read the file in columns, rather than rows?

#6 z80

    Valued Member

  • Members
  • PipPipPip
  • 104 posts

Posted 09 July 2007 - 04:39 PM

No, you have to write rows... the problem is that you are writing columns..

This is writing columns (since you have the X-axis as the outer loop):
            //Write Data Image To File

            for (int iterX = 0; iterX < vPlane.getVPlaneX(); iterX++){

                for(int iterY = 0; iterY < vPlane.getVPlaneY() * 3; iterY++){

                        tgaOutStream.write(vPlane._viewPlane[iterX][iterY]);

                }

That is why I am talking about that is the X-axis thingy you have to make 3 times wider (since the inner axis should have the color dimension hanging on it)..

I would skip the vPlane alltogether and write the pixels directly to the tga-file as you trace them with obj.calcIntersection()..

#7 appleGuy

    New Member

  • Members
  • PipPip
  • 25 posts

Posted 09 July 2007 - 04:52 PM

z80 said:

No, you have to write rows... the problem is that you are writing columns..

This is writing columns (since you have the X-axis as the outer loop):
            //Write Data Image To File

            for (int iterX = 0; iterX < vPlane.getVPlaneX(); iterX++){

                for(int iterY = 0; iterY < vPlane.getVPlaneY() * 3; iterY++){

                        tgaOutStream.write(vPlane._viewPlane[iterX][iterY]);

                }

That is why I am talking about that is the X-axis thingy you have to make 3 times wider (since the inner axis should have the color dimension hanging on it)..

I would skip the vPlane alltogether and write the pixels directly to the tga-file as you trace them with obj.calcIntersection()..

Ahhhhhhh!

Thank you so much!!!!!!

Simple mistake like you said, I wasnt sure how to store the image!!!!
Ive swaped the loops around and changed some arrays, now it works with the vPlane!


Thanks Again!

Cheers
-Alex





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users