News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Ray Casting and Correlated Projection Matrix

Started by johnsa, November 09, 2011, 09:06:48 AM

Previous topic - Next topic

johnsa

Hey,

This isn't specifically asm related, although I will port the working code to ASM.. for now i'm just trying to get a prototype done.

I've been working on trying to get a normal 3D pipeline and ray-caster to correlate, without much success. I've reviewed the maths
matrices and general workings of this for several days but still can't find the problem.

Let me start with the ray-cast:
I create a plane with coordinates:
(-4.0,-3.0,0.0) as top left
(4.0,3.0,0.0) as bottom right

So the view-plane is at Z=0.
The rays are created from an origin point at (0.0,0.0,-5.0)

This gives me the following two fields of view:

float horizFOV = ((float)(Math.Atan(4.0/5.0) * 180.0 / Math.PI)*2.0);
float vertFOV  = ((float)(Math.Atan(3.0/5.0) * 180.0 / Math.PI)*2.0);

These two values lead to:
77.319 degrees horizontal
61.927 degrees vertical.

I loop through the rays very simply for now:
Ray r = new Ray();
r.origin = new Vertex3(0,0,-5);

curY = -3.0;
for(y=0;y<600;y++)
{
   curX = -4.0;
   for(x=0;x<800;x++)
   {
      r.direction = (curX,curY,5.0);
      r.direction.Normalize();
      if(testSphere.Intersects(r))
      {
         DrawPixel(x,y,Blue);
      }
      curX += (8.0 / 800);
   }
   curY += (6.0 / 600);
}

Now my challenge is to be able to create a projection matrix, project normal (X,Y,Z,W) points in camera space
that corresponds exactly to what would be seen on screen from the above ray-casting.

For arguments sake I'll use a display of 800x600.

I setup the projection matrix as follows (I've tried a few different options here.. they all land up the same):

(This one is straight from DX SDK.. / MSDN)... row/col ordering:

   ;width = 800, height = 600 for aspect ratio.
   ;near plane = 0.0
   ;far plane = 10000.0

            float yScale = 1.0f / (float)Math.Tan((vertFOV/2) * 3.141592 / 180.0);
            float xScale = yScale / (width / height);

            m[0, 0] = xScale;
            m[1, 1] = yScale;
            m[3, 3] = 0.0f;
            m[2, 3] = 1.0f;
            m[2, 2] = far / (far - near);
            m[3, 2] = -near * far / (far - near);


(I am at this point wondering if it's the near/far planes that are causing the issue?)

Another similar matrix I've tried is (based on a horizontal FOV):

        //1  0  0  0
        //0  a  0  0
        //0  0  b  c
        //0  0  f  0
        //where:
        //a = the aspect ratio (width / height of screen)
        //b = f * (yon / (yon - hither))
        //c = -f * (yon * hither / (yon - hither))
        //f = sin(aov / 2) / cos(aov / 2)
        //aov = angle of view
        //yon = distance to far clipping plane
        //hither = distance to near clipping plane

So now to what I'm doing.. I use the loop above to ray-cast the sphere, which draws in blue on screen.
I then take the same sphere, use it's centre point and another derived point which is equal to cx+radius,cy,cz.
Both these points I project to 2D with the above, what this should give me is a 2D circle which is identical to the ray-cast.
(Drawn in red).

The scale is totally out, and depending on where the sphere is from the origin they don't center perfectly either.
At (0,0,10) they center correctly. The red projected sphere is quite a bit larger than the ray-cast one.

Any ideas?


FORTRANS

Hi,

   Try further out for the ray cast origin point.  You have an
awefully wide angle view that will be distorted.  You have 77.319
degrees.  Try something like 20 or 15 degrees.

Regards,

Steve N.

johnsa

Good point. I adjusted accordingly, but it hasn't really helped. I still cannot get a normal 4x4 projection matrix to produce a matching output.
Further more, I re-did the ray-cast numbers on paper, the value I land up with is slightly less than what is actually happening.

To best explain this I've attached my details, paper working and result ...


johnsa

Just to add context... the reason I need to do this is two-fold:

I need to know the screen area that a ray-traced sphere would occupy.. IE: is it <= 1 pixel

And I need to be able to draw a normal circle that conforms exactly to the ray-traced sphere..

johnsa

Just to make sure.. I've tried using the algebraic intersection method... luckily it produces exactly the same results as the geometric one.. So I don't think there is anything wrong with the intersection code.
Both produce an answer of 401/402 for the radius of the circle once drawn to screen.

The code is



            double a, b, c, d, ox, oy, oz;
            double t;

            // quadratic formula
            ox = r.origin.x - this.center.x;
            oy = r.origin.y - this.center.y;
            oz = r.origin.z - this.center.z;
            a = 2.0 * (r.direction.x * r.direction.x + r.direction.y * r.direction.y + r.direction.z * r.direction.z);
            b = 2.0 * (r.direction.x * ox + r.direction.y * oy + r.direction.z * oz);
            c = ox * ox + oy * oy + oz * oz - (this.radius * this.radius);

            d = b * b - 2.0 * a * c; // determinant
            if (d < 0.0) // no intersection at all
            {
                t = 0;
                return(false);
            }
            a = 1.0 / a;
            d = Math.Sqrt(d);
            t = (-d - b) * a;
            if (t >= 0.0) return(true); // smaller root wins
            t = (d - b) * a;
            if (t >= 0.0) return(true); // bigger root wins
            t = 0;
            return(false); // no root in range


johnsa

Ok, fixed the error in my working there... I now have the ray-trace working in according with the plan/paper workings.. as a stop-gap i've derived two projection equations based on that working that correlate perfectly...
only thing remains is to get a normal 4x4 homg. matrix to correlate to fit in with the rest of the pipeline.
I've attached the update image/workings/answers for anyone interested.


Farabi

What confuse me on OpenGL is, how to replace existing face color with a new one. I can have the depth texture but I dont know how to replace it.
Those who had universe knowledges can control the world by a micro processor.
http://www.wix.com/farabio/firstpage

"Etos siperi elegi"

Farabi

Raycasting should be easier if we can coloring each fragment on our object, by retrieving the Depth Buffer or making our own, we can easyly change the texture color, and shadow is autogenerated. Which system do you think feasible for this? I tried shadowing using OpenGL, I need to draw the object 3 times, even for drawing the object for 1 frame it took 1% CPU Usage. That is sucks.
Those who had universe knowledges can control the world by a micro processor.
http://www.wix.com/farabio/firstpage

"Etos siperi elegi"

Farabi

#8

R1
Those who had universe knowledges can control the world by a micro processor.
http://www.wix.com/farabio/firstpage

"Etos siperi elegi"

Farabi

First, you need to calculate how long the light is, and where it will stop, I created the function some time ago, but its gone. But polling each vertex is a bad idea, but lets see what ODE can do. If it is fast enough, we'll use it, if not, we invent our own using bounding box, it should be only 6 times comparing a box. Dead simple.

Lets say, the infinite ray is about 100 unit long, with about 45 degree we can have the formula

1st ray
X=Length*sin(A)
Z=Length*cos(A)
2nd ray
X=Length*sin(-A)
Z=Length*cos(-A)

So we had a 90 degree rayfield.
For Y, we just lets say, add it by half of the length above, and half below, so we got the final projection. If we used ODE, we can easyly create the rayfield as a mesh, and let it done the dirty job for us. We'll know which vertex hitted and from the Z value, we can create the depth buffer. It simple, we just give a white color with value depend on the lenght ratio. But I guess it will just fine, we just need how big the obstacle is. I think that simple.
Those who had universe knowledges can control the world by a micro processor.
http://www.wix.com/farabio/firstpage

"Etos siperi elegi"

Farabi

Guess what I found?  :cheekygreen: GL_COLOR_ARRAY
I want to see how did OpenGL method to coloring a vertex, I want it to coloring each fragment, but atleast in case of emergency, I can just coloring the texture and kept the original.
Those who had universe knowledges can control the world by a micro processor.
http://www.wix.com/farabio/firstpage

"Etos siperi elegi"

Farabi

Those who had universe knowledges can control the world by a micro processor.
http://www.wix.com/farabio/firstpage

"Etos siperi elegi"

Farabi

From the camera view, just create the depth texture, all what we see, that is the obstacle and the region of the light.



I see so I can only draw the scene 1, and then from the camera light view, I can create the shadow map.
Those who had universe knowledges can control the world by a micro processor.
http://www.wix.com/farabio/firstpage

"Etos siperi elegi"