tags:

views:

420

answers:

3
    for (iy = 0; iy < h; iy++)
    {
        double angy = (camera.fov_y / h) * iy;
        for (ix = 0; ix < w; ix++)
        {
            double angx = (camera.fov_x / w) * ix;
            //output[ix,iy].r = (int)Math.Round(255 * (angy / camera.fov_y);
            //output[ix,iy].b = (int)Math.Round(255 * (angy / camera.fov_y); 
            double tr = (angx / camera.fov_x) * 255D;
            double tb = (angy / camera.fov_y) * 255D;
            Console.Write("({0},{1})",Math.Round(tr),Math.Round(tb));

            output.SetPixel(ix, iy, Color.FromArgb(Convert.ToInt32(tr), 0, Convert.ToInt32(tb)) );
            Console.Write(".");
        }
        Console.WriteLine();
    }

Can anyone see any immediate problems with that code? The variables tr and tb always evaluate to 0.

I'm happy to provide more information if it is needed.

A: 

Don't forget to cast your integers to doubles. For example:

for (iy = 0; iy < h; iy++)
{
    double angy = ((double) camera.fov_y / h) * iy;
    for (ix = 0; ix < w; ix++)
    {
        double angx = ((double) camera.fov_x / (double) w) * (double) ix;
        output[ix,iy].r = (int) Math.Round(255 * (angy / camera.fov_y);
        output[ix,iy].b = (int) Math.Round(255 * (angy / camera.fov_y);
        double tr = (angx / camera.fov_x) * 255D;
        double tb = (angy / camera.fov_y) * 255D;
        Console.Write("({0},{1})",Math.Round(tr), Math.Round(tb));
        output.SetPixel(ix, iy, Color.FromArgb(
            Convert.ToInt32(tr), 0, Convert.ToInt32(tb)) );
        Console.Write(".");
    }
    Console.WriteLine();
}

Quick Reference:

 int * double = double
 int / double = double
 double * int = double
 double / int = double

 int * int = int
 int / int = int // be carefull here!

 1 / 10 = 0 (not 0.1D)
 10 / 11 = 0 (not 1)
 1D / 10 = 0.1D
 1 / 10D = 0.1D
 1D / 10D = 0.1D
Koistya Navin
While I suspect the problem is integer arithmetic, that line is a bad example: angx is already a double, so that line isn't the problem IMO. (Also 255D is a more compact way of writing (double)255.)
Jon Skeet
Still overkill - see my edited answer.
Jon Skeet
@Jon, good point, thanks.
Koistya Navin
+1  A: 

You haven't given the types for the other variables - in particular, what are the types of camera.fov_x and camera.fov_y? If they're both integers, then the lines initializing angx and angy will be evaluated using integer arithmetic.

This can be fixed by casting one of the operands:

double angy = ((double) camera.fov_y / h) * iy;

The fovy and fovx variables are already doubles though, this isn't the problem.

Could you give a complete example of this, which we can compile and test ourselves?

EDIT: Koistya Navin's edit is overkill. You only need one operand of an expression to be a double for the whole thing to be computed using double arithmetic. (It needs to be the right expression though - if you do (a/b) * c and cast c a double, the multiplication will be done with double arithmetic but a/b might still be done as integers.)

Here's the listing changed appropriately to make sure double arithmetic is used everywhere it should be:

// Changed loops to declare the variable, for stylistic purposes
for (int iy = 0; iy < h; iy++)
{
    // Changed here - cast camera.fov_y
    double angy = ((double) camera.fov_y / h) * iy;
    for (int ix = 0; ix < w; ix++)
    {
        // Changed here - cast camera.fov_x
        double angx = ((double) camera.fov_x / w) * ix;
        //output[ix,iy].r = (int)Math.Round(255 * (angy / camera.fov_y);
        //output[ix,iy].b = (int)Math.Round(255 * (angy / camera.fov_y); 
        double tr = (angx / camera.fov_x) * 255D;
        double tb = (angy / camera.fov_y) * 255D;
        Console.Write("({0},{1})", Math.Round(tr), Math.Round(tb));

        output.SetPixel(ix, iy, Color.FromArgb(Convert.ToInt32(tr), 
                                               0,
                                               Convert.ToInt32(tb)) );
        Console.Write(".");
    }
    Console.WriteLine();
}
Jon Skeet
I've changed a few lines around since I posted, but here is the complete source code.Program.cs - http://pastebin.com/f4c133638Classes.cs - http://pastebin.com/d18b37a35MiscFunctions.cs - http://pastebin.com/febb33ca
Charlie Somerville
I'll try that now...
Charlie Somerville
You legend!It works perfectly! Thanks.
Charlie Somerville
By the way, I know the entire code is pretty overkill for what it produces, but I'm aiming to make a ray-tracing engine, so that's where the `ang` bits and `camera.fov` bits come in ;)
Charlie Somerville
+1  A: 

It know it's not part of your original question, but using SetPixel(..) is not very efficient and could be a problem if you are planning to use it in a ray-tracing engine.

You might want to use the LockBits() method, see this answer and this one for more details. They other way to go is to access the data using "unsafe" C# code, which allows you to uses pointers to the data. See this question for more info, I got a ~x2 speed-up by using "unsafe" code.

Matt Warren