Showing posts with label Engineering. Show all posts
Showing posts with label Engineering. Show all posts

Tuesday, November 12, 2013

Ray-tracing Refraction - Floating Point Error

To implement refraction in ray-tracing rendering, we can simply use the refraction equation:
sin(theta1)/sin(theta2) = n2/n1

To compute sin(theta1), simply:
cos(theta1)= v1.dot(N);
sin(theta1) = sqrt(1-cos(theta1) * cos(theta1)); 

where v1 is the incomming ray direction, and N is the surface normal.
However, there may be trouble when this implementation runs in computer. In C++, since we can't avoid floating point error, when v1 is almost perpendicular to the surface, that is, v1 and N almost the same (or they just be the same), cos(theta1) could slightly greater than 1 (something like 1.00001). Then, this result would cause:
1-cos(theta1) * cos(theta1) < 0
And sqrt(a) would return invalid result if a<0. So that sin(theta1) becomes a invalid value. Eventually, all the computation mess up. The pixel we want to shade becomes an error pixel. 
To avoid this, simply put a check routine like:
cos(theta1) = min(1.0f, v1.dot(N))

Never trust floating point number!! 

Wednesday, April 10, 2013

Be careful when dealing with C++ floating point.

Look at this piece of code:

Vector3 colPlaneNor;

float dx = abs(aabb1->getPosition().x() - aabb2->getPosition().x());
float dy = abs(aabb1->getPosition().y() - aabb2->getPosition().y());

if(dx < (aabb1->_width + obb2->_width)/2.0f)

    colPlaneNor = Vector3::UNIT_Y;
else if(dy < (aabb1->_height + aabb2->_height)/2.0f)
    colPlaneNor = Vector3::UNIT_X;

The idea of these lines of code is to determine the collision plane normal when two AABB boxes collided. The problem here is, floating point calculation is not 100% accurate. Even if the true is

dx == (aabb1->_width + obb2->_width)/2.0f,
 and
dy < (aabb1->_height + aabb2->_height)/2.0f

But in C++, the floating point number dx may slightly less than
(aabb1->_width + obb2->_width ) / 2.0f

That will cause the code pass the if()test first and set the collision plane normal to a wrong vector.
My solution here is to make the threshold a little bit lower:


if(dx < (aabb1->_width + aabb2->_width)*.99f/2.0f)
    colPlaneNor = Vector3::UNIT_Y;
else if(dy < (aabb1->_height + aabb2->_height)*.99f/2.0f)
    colPlaneNor = Vector3::UNIT_X;

Instead of compare the actual sum, I multiply the sum by 0.99. So even if dx is slightly lower than the actual result, it won't pass the if() test and jump into the else if(). If the collision plane normal should be normal Y, dy should still smaller (aabb1->_height + aabb2->_height)*.99f/2.0f.
If both dx and dy are actually equal to the sums, that means the two AABB is colliding on the coner, or maybe very closed to the corner. In this case I can make a default vector for the collision plane normal, such as normal X.

Monday, February 11, 2013

Code works first, Optimize it later

This week I implement some features on our prototype. Now in our prototype, the worker can move the Tech Parts back to the base but with low moving speed. And worker can collect oxygen pack as their HP refill (we also have 3D HP bar for workers!),  a minimap showing position information of units and base.
Unity is a powerful tool to make prototype work. I don't need to worry too much about run time error. In Unity, even my script have some stupid operation (use null pointer, etc.), the prototype game can still run, then Unity has its log to indicate where goes wrong.
Also, I haven't consider too much details when I coding. I think that should be how things start, even in software engineering. We can always go on detail design, build framework architecture, and code in deep until final product come out. But at first, is this product, idea, or concept worth to implement? Prototype is for answering this question. We don't need to think too much detail in prototype. All we need to worry is the core concept, core mechanic of the game.
As the title said, after rushing some garbage code, we should think about the real game. What game engine should we use? How the architecture should be? I will prefer to use OGRE as our basic engine. There are several reasons. First, it is completely open-source, so we don't need to worry about license like UDK. Second, OGRE also has its wiki, forum, so that we can always go to find someone for help, and the forum is kept updating. Third, OGRE is a C++ engine, and there are several concept similar to what we learn in Game Engineering II, so that it is a good practice for our engineers. OGRE can also be a good reference for our Game Engineering assignments.

OGRE official website: http://www.ogre3d.org/

Thanks for our producer Zeph, we have our own awesome website. Check it out!

Team dawgz: http://www.teamdawgz.com/