• entries
18
19
• views
14872

We are in desolate places as dead men.

## Texture Hunting in the Middle East

I've been trying to build up a texture library in order to texture map my levels. I brought my digital camera to the park here in Knoxville, and took some shots of the grass, some rocks by the river, the sky. They were nice but I needed a little more variety.

So I logged onto expedia and bought two round airline trip tickets to the Middle East. The first stop was in Mersin in southeastern Turkey, where I did not see another tourist at all. Next we traveled to Goreme in the middle of the country. We ended up in Istanbul. The entire trip took about half a month. While there we went hot air ballooning, horse back riding, trekking, white water rafting, and abseiling. Many oppurtunities to sample some textures.

Here is a small sample of what I was able to collect. I have hundreds more of these that need processing. If anyone is interested in the full collection in high resolution, let me know. I will let you have these to use in a non-commercial game royalty free.

We made it back more or less intact. My wife suffered from a fractured hand, and several lacerations, cuts, and scrapes. I only had to visit a rural doctor once, where he loaded me up with four unknown prescription drugs. One of our guides was bitten by a scorpion and required hospitalization, another guide engaged in a brutal fistfight for some unknown reason, another fell down a series of stone steps and broke his arm, and yet another stepped on a rusty nail and had to be taken to the hospital.

And for those that are interested, here is a shot from our hotair balloon as we accidently violated the airspace over a maximum security prison. Maybe I will make a Turkish prison level.

I finished coded and implementing the quad-tree data structure to handle my collision detection geometry. I figured that a quad-tree would do the trick because I see no reason to partition the geometry along the y axis. If my level geometry consists of several rooms above rooms, I don't think it will affect the framerate that much.

Basically I recursively subdivide the collision detection geometry into a 2D quad-tree, ignoring the y values. Then during a collision pass I build a 2D bounding box around my bounding ellipsoid representing the player's current position and the ellipsoid representing the players final position. I then, non-recursively, test this bounding box against the subdivided quads. Each quad that contained the player's bounding box is then passed to the collision detection routine.

It works well, but I need some larger level geometry to test it. With the partial test level I have constructed consisting of 555 triangles, an average of 11 triangles was passed to the collision routine. This was with 3 levels of recursion when building the quad-tree.

Next I will work on finishing the test level geometry in Maya and then texturing and populating the rooms with various geometry. This will give me a good testing environment to finish up the visibility culling. It should also make for some more interesting screenshots.

As far as visibility culling is concerned, I have decided that I will do a basic frustum cull on the bounding boxes of each object. I will then render all the "room" geometry. Finally, I will make a GL_ARB_occlusion_query call on each "non-room" bounding box that passed the frustum cull. If the occlusion query call returns an integer greater than my threshold, I will send the geometry down the pipe. My game will consists primarily of indoor environments so this approach should allow for fast framerates.

I also have a seperate code that allows me to run a Perlin noise filter through a mesh. I want to incorporate this vertex shader into my engine for various animated effects. The first geometry I will tweak with this shader will be flames. Torchlight will play a key role in my game and I would like for it to look nice.

-----------------

On a different note, I have spent a couple of evenings last week reading Alan Watt's 3D Computer Graphics (Third Edition). This was the textbook we used in Computer Graphics CS594 at the University of Tennessee when I was a teaching assistant for the class. Since then, the professor has changed to Real-Time Rendering (2nd Edition), which I currently have on order from amazon.

In the first chapter entitled, Mathematical Fundamentals of Computer Graphics I noticed several errors.

On page 14, the last sentence on the page reads, "or the angle between two
vectors is the dot product of their normalized versions". This statement
is false. I believe what the author meant to say was "or the cosine of
the angle between two vectors is the dot product of their normalized
versions".

On page 19, the last paragraph second sentence reads "This means that the
ray is in the half space, defined by the plane that does not contain the
polygon". This too is a false statement. I believe what the author meant
to say was "This means that the ray is in the half space, defined by the
plane that does not contain the polyhedron".

On page 24 there are two diagrams at the bottom of the page. The first
has a caption that reads "R = I + 2N cos theta". This is not true. What
the author probably meant was "R = I + 2N cos phi". This error is particularly
brutal because theta is used to describe another angle in the same diagram.

These mistakes are unfortunate, because they can lead the reader in the wrong direction. Watt doesn't do a great job of explaining the math in the first place, often leaving it to the reader to fill in the gaps. This approach might be suitable for a quick refresher for someone that is already familar with the concepts, but the errors might make this text particularly treacherous for someone learning for the first time.

There is also no errata that I could find online.

## Paul Nettle, Night of the Raven, and Adaptoids

In a recent entry I made some comments about Paul Nettle's collision detection article here on gamedev. You can find his article here:

General Collision Detection for Games Using Ellipsoids

I spent some time this weekend combing through my code to try to find my mistakes. I found them and fixed them. Long story short, with the exception of adding one parallel check to abort computations if a collision could never occur (which is necessary or anomalies will appear), his pseudo-code is correct. I have implemented it fully and it works just as advertised.

In fact, his article is the best I have seen in regards to implementing sliding plane collision detection. It is still used widely in games today (i.e. Oblivion) and works really well with human shaped ellipsoids.

I went on a shopping spree also. I ordered the following books and games from Amazon:

Mathematics for 3D Game Programming and Computer Graphics Second Edition
Real-Time Rendering (2nd Edition)
OpenGL(R) Programming Guide : The Official Guide to Learning OpenGL(R), Version 2 (5th Edition)

and I saw Night of the Raven was finally translated to English, so although I still own the original Gothic II, I ordered this to get the expansion...
Gothic 2 Gold

I wrote the pseudo-code for a quad-tree to sort my collision detection geometry. I also pulled down a few frustum culling papers that I will leverage to cull the actual scene geometry. These are the two coding events that will occur next in my engine.

-------------

On the gaming front, I was able to play a little bit of Oblivion. I am amazed at the technology every time I play this. It is quite possibly the best RPG to date. I also played a little online of Fight Night 3 on the 360, which is also a wonderful game, with my brother that lives in D.C.

I recently hooked up my PC (which is in my office) to my home theater (that is in my living room). The whole project involved drilling through the floor several times, crawling around under the house running cables, and once nearly receiving a concussion when a huge oak piece of my home theater cabinet crashed into my skull.

But I have it hooked up now and even bought an Adaptoid for much more money that I should have spent on one. Ever heard of an adaptoid? It basically allows you to make your old Nintendo 64 into a programmable PC joystick. It is a wonderful device that is no longer being produced. So if you want one, you have to compete with the rest of the geeks on eBay. But the experience playing the original Golden Ax emulated through Mame on my big screen and surround sound with the N64 joystick is priceless. :)
-------------------

## Smooth key scrolling

I fixed the key repeat issue with my engine tonight. Before, I was relying on the operating system key repeat setting to implement movement. So when the player held down the 'W' key, for example, the engine would move forward a frame, pause, and then start smooth scrolling forward.

There were two problems with this. First, the pause before scrolling kicked in was ugly. Second, the player could only hold down one key at a time. There was no way to hold down 'w' and 'a' at the same time and move diagonally. Now all that is fixed.

It works well with the collision detection and sliding planes also. Basically, I used the keypress routine here (as found on the old lighthouse3D website)

#include
#include

#include

float angle=0.0,deltaAngle = 0.0,ratio;
float x=0.0f,y=1.75f,z=5.0f;
float lx=0.0f,ly=0.0f,lz=-1.0f;
GLint snowman_display_list;
int deltaMove = 0;

void changeSize(int w, int h)
{

// Prevent a divide by zero, when window is too short
// (you cant make a window of zero width).
if(h == 0)
h = 1;

ratio = 1.0f * w / h;
// Reset the coordinate system before modifying
glMatrixMode(GL_PROJECTION);

// Set the viewport to be the entire window
glViewport(0, 0, w, h);

// Set the clipping volume
gluPerspective(45,ratio,1,1000);
glMatrixMode(GL_MODELVIEW);
gluLookAt(x, y, z,
x + lx,y + ly,z + lz,
0.0f,1.0f,0.0f);

}

void drawSnowMan() {

glColor3f(1.0f, 1.0f, 1.0f);

// Draw Body
glTranslatef(0.0f ,0.75f, 0.0f);
glutSolidSphere(0.75f,20,20);

glTranslatef(0.0f, 1.0f, 0.0f);
glutSolidSphere(0.25f,20,20);

// Draw Eyes
glPushMatrix();
glColor3f(0.0f,0.0f,0.0f);
glTranslatef(0.05f, 0.10f, 0.18f);
glutSolidSphere(0.05f,10,10);
glTranslatef(-0.1f, 0.0f, 0.0f);
glutSolidSphere(0.05f,10,10);
glPopMatrix();

// Draw Nose
glColor3f(1.0f, 0.5f , 0.5f);
glRotatef(0.0f,1.0f, 0.0f, 0.0f);
glutSolidCone(0.08f,0.5f,10,2);
}

GLuint createDL() {
GLuint snowManDL;

// Create the id for the list
snowManDL = glGenLists(1);

// start list
glNewList(snowManDL,GL_COMPILE);

// call the function that contains the rendering commands
drawSnowMan();

// endList
glEndList();

return(snowManDL);
}

void initScene() {

glEnable(GL_DEPTH_TEST);
snowman_display_list = createDL();

}

void orientMe(float ang) {

lx = sin(ang);
lz = -cos(ang);
gluLookAt(x, y, z,
x + lx,y + ly,z + lz,
0.0f,1.0f,0.0f);
}

void moveMeFlat(int i) {
x = x + i*(lx)*0.1;
z = z + i*(lz)*0.1;
gluLookAt(x, y, z,
x + lx,y + ly,z + lz,
0.0f,1.0f,0.0f);
}

void renderScene(void) {

if (deltaMove)
moveMeFlat(deltaMove);
if (deltaAngle) {
angle += deltaAngle;
orientMe(angle);
}

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw ground

glColor3f(0.9f, 0.9f, 0.9f);
glVertex3f(-100.0f, 0.0f, -100.0f);
glVertex3f(-100.0f, 0.0f, 100.0f);
glVertex3f( 100.0f, 0.0f, 100.0f);
glVertex3f( 100.0f, 0.0f, -100.0f);
glEnd();

// Draw 36 SnowMen

for(int i = -3; i 3; i++)
for(int j=-3; j 3; j++) {
glPushMatrix();
glTranslatef(i*10.0,0,j * 10.0);
glCallList(snowman_display_list);;
glPopMatrix();
}
glutSwapBuffers();
}

void pressKey(int key, int x, int y) {

switch (key) {
case GLUT_KEY_LEFT : deltaAngle = -0.01f;break;
case GLUT_KEY_RIGHT : deltaAngle = 0.01f;break;
case GLUT_KEY_UP : deltaMove = 1;break;
case GLUT_KEY_DOWN : deltaMove = -1;break;
}
}

void releaseKey(int key, int x, int y) {

switch (key) {
case GLUT_KEY_LEFT :
case GLUT_KEY_RIGHT : deltaAngle = 0.0f;break;
case GLUT_KEY_UP :
case GLUT_KEY_DOWN : deltaMove = 0;break;
}
}

void processNormalKeys(unsigned char key, int x, int y) {

if (key == 27)
exit(0);
}

int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(640,360);
glutCreateWindow("SnowMen from Lighthouse 3D");

initScene();

glutIgnoreKeyRepeat(1);
glutKeyboardFunc(processNormalKeys);
glutSpecialFunc(pressKey);
glutSpecialUpFunc(releaseKey);

glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);

glutReshapeFunc(changeSize);

glutMainLoop();

return(0);
}

I already have a timer built into the engine to calculate framerate. Next I will modify the code to implement framerate independence.

I also want to implement a perlin noise shader soon in Cg. I plan to use this shader for various effects throughout the levels. I recently had to give a presentation regarding GPU depth buffers, so I have Cg fresh on my mind.

Sound is also on the horizon, and this is something that I do not have much experience with at the moment. I believe I will use openAl to do this, but I really know nothing about it currently. It should be interesting learning about it.

Finally, I found a bug the other day in my code that was responsible for constructing my data structures from OBJs. It was a small little looping bug, but it caused certain faces to be added twice, while the face count was only incremented once. Since the faces that were added twice were identical, there was no noticeable difference when rendering. Unfortunately, all my rendering benchmarks are now suspect. Suspect for the better, but suspect nonetheless. I might benchmark again sometime to get more accurate results, but for the moment I would like to continue coding.

## Leveling Up

If the rules of life were really like the game Oblivion I would have woke up this morning and thought...

"So that's how you do it. What once was a struggle has now become second nature. Please distribute attribute points."

I finally finished the collision detection routine in my 3D engine. This was no easy task for me and there were many times that I thought I had reached a barrier that I could not overcome. I sometimes felt at the verge of panic. All this work so far only to be defeated.

It seemed like I almost had it working several times. And the worst was when I thought I had it working. I would cautiously become optimistic only to have the chair pulled out from under me as I sat down. Inevitably, I would discover someway to clip through a corner and find the camera outside the walls of the test level.

While although shady company, printf has been my constant companion through collision detection hell. Here is a sample of one of the last debug iterations.

recursion level: 1
The distance the player wants to travel is 1.100000
The player is currently at [sourcePoint] 6.184948 0.000000 0.780793
The velocity vector is -0.164489 0.000000 -1.087632
The normalized velocity vector is -0.149535 0.000000 -0.988756
The player wants to move to 6.020459 0.000000 -0.306839
The bounding sphere radius is 1.000000
Now traversing triangle list in zone object.

Now considering triangle #24.
Point 1 on triangle: 7.000000 -1.500000 0.000000
Point 2 on triangle: 12.000000 -1.500000 0.000000
Point 3 on triangle: 7.000000 3.500000 0.000000
The origin of the plane is (a point on the triangle): 7.000000 -1.500000 0.000000
Normalized plane normal (normal of the triangle): 0.000000 0.000000 1.000000
The distance from the sphere origin to the plane is absolute 0.780793 relative 0.780793.
NOTE: If value is negative we are dealing with a backface and no additional tests will occur.
The bounding sphere is embedded in the triangle plane.
setting planeCollisionPoint to 6.184948 0.000000 0.000000 for embedded sphere.
Plane intersection point is 6.184948 0.000000 0.000000
**** crossings: 0
The planeIntersectionPoint is not contained within the triangle
Closest Point on Triangle to the collision point: 7.000000 -1.500000 0.000000
polygonIntersectionPoint is 7.000000 -1.500000 0.000000
The distance from the polygonIntersectionPoint and the sourcePoint is 1.877218
(tt) The distance from the polygonIntersectionPoint to the sphereIntersectionPoint is -1.000000

Now considering triangle #25.
Point 1 on triangle: 7.000000 -1.500000 0.000000
Point 2 on triangle: 7.000000 3.500000 0.000000
Point 3 on triangle: 7.000000 -1.500000 -5.000000
The origin of the plane is (a point on the triangle): 7.000000 -1.500000 0.000000
Normalized plane normal (normal of the triangle): -1.000000 0.000000 0.000000
The distance from the sphere origin to the plane is absolute 0.815052 relative 0.815052.
NOTE: If value is negative we are dealing with a backface and no additional tests will occur.
The bounding sphere is embedded in the triangle plane.
setting planeCollisionPoint to 7.000000 0.000000 0.780793 for embedded sphere.
Plane intersection point is 7.000000 0.000000 0.780793
**** crossings: 0
The planeIntersectionPoint is not contained within the triangle
Closest Point on Triangle to the collision point: 7.000000 -0.500000 0.000000
polygonIntersectionPoint is 7.000000 -0.500000 0.000000
The distance from the polygonIntersectionPoint and the sourcePoint is 1.234483
(tt) The distance from the polygonIntersectionPoint to the sphereIntersectionPoint is -1.000000

There was no collision with any triangle. Moving sphere origin to 6.020459 0.000000 -0.306839

recursion level: 1
The distance the player wants to travel is 1.100000
The player is currently at [sourcePoint] 6.020459 0.000000 -0.306839
The velocity vector is 0.336267 0.000000 -1.047342
The normalized velocity vector is 0.305697 0.000000 -0.952129
The player wants to move to 6.356726 0.000000 -1.354181
The bounding sphere radius is 1.000000
Now traversing triangle list in zone object.

Now considering triangle #24.
Point 1 on triangle: 7.000000 -1.500000 0.000000
Point 2 on triangle: 12.000000 -1.500000 0.000000
Point 3 on triangle: 7.000000 3.500000 0.000000
The origin of the plane is (a point on the triangle): 7.000000 -1.500000 0.000000
Normalized plane normal (normal of the triangle): 0.000000 0.000000 1.000000
The distance from the sphere origin to the plane is absolute 0.306839 relative -0.306839.
NOTE: If value is negative we are dealing with a backface and no additional tests will occur.

Now considering triangle #25.
Point 1 on triangle: 7.000000 -1.500000 0.000000
Point 2 on triangle: 7.000000 3.500000 0.000000
Point 3 on triangle: 7.000000 -1.500000 -5.000000
The origin of the plane is (a point on the triangle): 7.000000 -1.500000 0.000000
Normalized plane normal (normal of the triangle): -1.000000 0.000000 0.000000
The distance from the sphere origin to the plane is absolute 0.979541 relative 0.979541.
NOTE: If value is negative we are dealing with a backface and no additional tests will occur.
The bounding sphere is embedded in the triangle plane.
setting planeCollisionPoint to 7.000000 0.000000 -0.306839 for embedded sphere.
Plane intersection point is 7.000000 0.000000 -0.306839
**** crossings: 1
The planeIntersectionPoint lies within the triangle.
The polygonIntersectionPoint equals the planeIntersectionPoint
polygonIntersectionPoint is 7.000000 0.000000 -0.306839
The distance from the polygonIntersectionPoint and the sourcePoint is 0.979541

SANITY ERROR: The polygonIntersectionPoint is within the bounding sphere.
A previous logic error did not properly detect a collision.
ABORTING

But a long story short: I did it. I implemented collision detection with recursive sliding planes and gravity.

The document I found most helpful was General Collision Detection for Games Using Ellipsoids by Paul Nettle. You can find it here:
https://www.gamedev.net/reference/articles/article1026.asp

This wasn't a perfect article though. I found a few errors. Or at least I was not able to implement exactly what Paul was suggesting. In particular, how the sliding planes itself were calculated seemed wrong to me. Paul suggested that sliding planes be calculated like this:

Point slidePlaneOrigin = nearestPolygonIntersectionPoint;
Vector slidePlaneNormal = nearestPolygonIntersectionPoint - sourcePoint;

When implemented like this, a sliding plane would be calculated that was not parallel to the actual triangle. Paul writes, "The normal of this [sliding] plane is the vector from the intersection point to the center of the sphere". However, this created more of a "bouncing plane" rather than a true sliding plane when I implemented this. To solve this problem, I simply used the original triangles normal for the sliding plane normal. This seems to work just fine and creates a nice smooth sliding plane on which to project the movement vector.

There were a couple of small inconsistencies that could cause problems. One, the order of arguments given in his routines were not consistent with the order that he passed them in the pseudo code. This problem was compounded by the almost cryptic variable names (i.e. r, rV, s, sR). In the psuedo code, for example, Paul would write:

Double t = intersectEllipse(sourcePoint, radiusVector, polygonIntersectionPoint, negativeVelocityVector);

However, the actual pseodo-code intersectEllipse routine does not accept the arguements in this order. Additionally, radiusVector is really a double while negativeVelocityVector is actually a vector. He also uses '*' to denote a scalar multiplication and then immediatly uses '*' to denote dot product. While it can eventually be deciphered, it caused me a little uneccesary pain. I am still in debt to Paul Nettle's document, however; I used it heavily to implement my collision detection.

One thing that Paul skipped over entirely in his article was point in polygon strategies. In the pseudo-code he would say

if (planeIntersectionPoint is not within the current polygon)

So I found another article that was really good at explaining these strategies, appropriately names Point in Polygon Strategies by Eric Haines. In fact, this article appears in Graphics Gems IV. Apparently the full article is better than the one you can find on the internet, but it is still very useful.

Another really good article was Intersection of Convex Objects: The Method of Separating Axes by David Eberly.

And now I am ready to move on to another area of development. Collision detection was a huge obstacle for me to overcome and my morale has been raised considerably by being able to overcome it. I have spent so much of my free time and energy on this particular area that I seriously felt like weeping for joy when it finally worked correctly. The more time and energy I poured into this, the greater the anxiety of possible failure. But when it finally worked correctly, all that anxiety left.

Here is screenshot of the expanded test level I was using to test this. I added some stairs to make sure gravity was working as expected and created a quarter dome room to test the recursive sliding plane calls. It all looks beautiful. At least from my vantage.

## collision and backgrounds

I have basic collision detection working now. I still need to make the routine recursive and add sliding. Geometry that can collide is now a derived zone class of the world object. Only zone geometry is considered for collision tests. Selectable items will be another derived class of the world object class.

Here is a background I rendered to use as a backdrop texture against transparent windows, etc. I may explore around more with different fractals, but as soon as I decide upon a partitcular look, I will try to keep the landscape scenery consistent.

1900x1200 uncompressed png version

## Quake 3 running at 11,520x3072 resolution

Have you ever seen Quake 3 running at 11,520 x 3072 resolution? Well, here is your chance. It required 27 DLP projectors running at 1280x1024 each to do this:

http://members.gamedev.net/jdaniel/movies/quake3_11520x3072.mpg

## ray casting and printf

...fun with printf and the ray equation.

...

Ray origin (players current position): -24.394674 0.000000 8.963964
Normalized Ray vector (direction player wants to move): -0.750111 0.000000 0.661312
Point on plane (a point on this polygon): -105.251305 -131.641800 -105.308907
Normalized plane normal (normal of the polygon): 0.000070 -1.000000 -0.000217
Distance from the coordinate system origin to the plane: 131.657335
There is no intersection.

Ray origin (players current position): -25.219797 0.000000 9.691408
Normalized Ray vector (direction player wants to move): -0.736096 0.000000 0.676877
Point on plane (a point on this polygon): -131.641815 -131.641815 -105.251305
Normalized plane normal (normal of the polygon): -0.000291 -1.000000 0.000000
Distance from the coordinate system origin to the plane: 131.680150
An intersection will occur at 614149.375000 units from the ray's origin.
Point of intersection: -452098.389435 0.000000 415713.071655

Ray origin (players current position): -25.219797 0.000000 9.691408
Normalized Ray vector (direction player wants to move): -0.736096 0.000000 0.676877
Point on plane (a point on this polygon): -131.641815 -131.641815 -105.251305
Normalized plane normal (normal of the polygon): -0.000291 -1.000000 0.000000
Distance from the coordinate system origin to the plane: 131.680150
An intersection will occur at 614149.375000 units from the ray's origin.
Point of intersection: -452098.389435 0.000000 415713.071655

Ray origin (players current position): -25.219797 0.000000 9.691408
Normalized Ray vector (direction player wants to move): -0.736096 0.000000 0.676877
Point on plane (a point on this polygon): -105.251305 -131.641800 -105.308907
Normalized plane normal (normal of the polygon): 0.000070 -1.000000 -0.000217
Distance from the coordinate system origin to the plane: 131.657335
There is no intersection.

Ray origin (players current position): -26.029503 0.000000 10.435972
Normalized Ray vector (direction player wants to move): -0.724172 0.000000 0.689620
Point on plane (a point on this polygon): -131.641815 -131.641815 -105.251305
Normalized plane normal (normal of the polygon): -0.000291 -1.000000 0.000000
Distance from the coordinate system origin to the plane: 131.680150
An intersection will occur at 624261.437500 units from the ray's origin.
Point of intersection: -452098.383125 0.000000 430513.545323

Ray origin (players current position): -26.029503 0.000000 10.435972
Normalized Ray vector (direction player wants to move): -0.724172 0.000000 0.689620
Point on plane (a point on this polygon): -131.641815 -131.641815 -105.251305
Normalized plane normal (normal of the polygon): -0.000291 -1.000000 0.000000
Distance from the coordinate system origin to the plane: 131.680150
An intersection will occur at 624261.437500 units from the ray's origin.
Point of intersection: -452098.383125 0.000000 430513.545323

Ray origin (players current position): -26.029503 0.000000 10.435972
Normalized Ray vector (direction player wants to move): -0.724172 0.000000 0.689620
Point on plane (a point on this polygon): -105.251305 -131.641800 -105.308907
Normalized plane normal (normal of the polygon): 0.000070 -1.000000 -0.000217
Distance from the coordinate system origin to the plane: 131.657335
There is no intersection.

Ray origin (players current position): -26.826092 0.000000 11.194554
Normalized Ray vector (direction player wants to move): -0.704634 0.000000 0.709571
Point on plane (a point on this polygon): -131.641815 -131.641815 -105.251305
Normalized plane normal (normal of the polygon): -0.000291 -1.000000 0.000000
Distance from the coordinate system origin to the plane: 131.680150
An intersection will occur at 641569.562500 units from the ray's origin.
Point of intersection: -452098.407156 0.000000 455250.467820

Ray origin (players current position): -26.826092 0.000000 11.194554
Normalized Ray vector (direction player wants to move): -0.704634 0.000000 0.709571
Point on plane (a point on this polygon): -131.641815 -131.641815 -105.251305
Normalized plane normal (normal of the polygon): -0.000291 -1.000000 0.000000
Distance from the coordinate system origin to the plane: 131.680150
An intersection will occur at 641569.562500 units from the ray's origin.
Point of intersection: -452098.407156 0.000000 455250.467820

Ray origin (players current position): -26.826092 0.000000 11.194554
Normalized Ray vector (direction player wants to move): -0.704634 0.000000 0.709571
Point on plane (a point on this polygon): -105.251305 -131.641800 -105.308907
Normalized plane normal (normal of the polygon): 0.000070 -1.000000 -0.000217
Distance from the coordinate system origin to the plane: 131.657335
There is no intersection.

Ray origin (players current position): -27.601189 0.000000 11.975082
Normalized Ray vector (direction player wants to move): -0.669130 0.000000 0.743145
Point on plane (a point on this polygon): -131.641815 -131.641815 -105.251305
Normalized plane normal (normal of the polygon): -0.000291 -1.000000 0.000000
Distance from the coordinate system origin to the plane: 131.680150
An intersection will occur at 675609.437500 units from the ray's origin.
Point of intersection: -452098.404160 0.000000 502087.743091

Ray origin (players current position): -27.601189 0.000000 11.975082
Normalized Ray vector (direction player wants to move): -0.669130 0.000000 0.743145
Point on plane (a point on this polygon): -131.641815 -131.641815 -105.251305
Normalized plane normal (normal of the polygon): -0.000291 -1.000000 0.000000
Distance from the coordinate system origin to the plane: 131.680150
An intersection will occur at 675609.437500 units from the ray's origin.
Point of intersection: -452098.404160 0.000000 502087.743091

Ray origin (players current position): -27.601189 0.000000 11.975082
Normalized Ray vector (direction player wants to move): -0.669130 0.000000 0.743145
Point on plane (a point on this polygon): -105.251305 -131.641800 -105.308907
Normalized plane normal (normal of the polygon): 0.000070 -1.000000 -0.000217
Distance from the coordinate system origin to the plane: 131.657335
There is no intersection.

Ray origin (players current position): -28.337233 0.000000 12.792542
Normalized Ray vector (direction player wants to move): -0.634730 0.000000 0.772734
Point on plane (a point on this polygon): -131.641815 -131.641815 -105.251305
Normalized plane normal (normal of the polygon): -0.000291 -1.000000 0.000000
Distance from the coordinate system origin to the plane: 131.680150
An intersection will occur at 712224.562500 units from the ray's origin.
Point of intersection: -452098.408297 0.000000 550373.130179

Ray origin (players current position): -28.337233 0.000000 12.792542
Normalized Ray vector (direction player wants to move): -0.634730 0.000000 0.772734
Point on plane (a point on this polygon): -131.641815 -131.641815 -105.251305
Normalized plane normal (normal of the polygon): -0.000291 -1.000000 0.000000
Distance from the coordinate system origin to the plane: 131.680150
An intersection will occur at 712224.562500 units from the ray's origin.
Point of intersection: -452098.408297 0.000000 550373.130179

Ray origin (players current position): -28.337233 0.000000 12.792542
Normalized Ray vector (direction player wants to move): -0.634730 0.000000 0.772734
Point on plane (a point on this polygon): -105.251305 -131.641800 -105.308907
Normalized plane normal (normal of the polygon): 0.000070 -1.000000 -0.000217
Distance from the coordinate system origin to the plane: 131.657335
There is no intersection.

Ray origin (players current position): -29.035435 0.000000 13.642550
Normalized Ray vector (direction player wants to move): -0.604598 0.000000 0.796530
Point on plane (a point on this polygon): -131.641815 -131.641815 -105.251305
Normalized plane normal (normal of the polygon): -0.000291 -1.000000 0.000000
Distance from the coordinate system origin to the plane: 131.680150
An intersection will occur at 747718.500000 units from the ray's origin.
Point of intersection: -452098.401844 0.000000 595594.222113

Ray origin (players current position): -29.035435 0.000000 13.642550
Normalized Ray vector (direction player wants to move): -0.604598 0.000000 0.796530
Point on plane (a point on this polygon): -131.641815 -131.641815 -105.251305
Normalized plane normal (normal of the polygon): -0.000291 -1.000000 0.000000
Distance from the coordinate system origin to the plane: 131.680150
An intersection will occur at 747718.500000 units from the ray's origin.
Point of intersection: -452098.401844 0.000000 595594.222113

...

## Preliminary level...

It snowed here over the weekend, so I finally convinced myself to do some work on this project. I am about ready to code up the collision detection, and I need some level geometry in order to test.

Here is a quick pencil sketch I jotted out on graph paper. I ran the image through a filter after I scanned it to give it a "blueprint" look.

So I brought out Maya to create the geometry. I realized I was a little rusty and had pull down the reference and utilize the online docs.

After exporting to OBJ, I pulled it into the engine. I had to scale the geometry and turn on two-sided lighting. I also changed the field of view and tweaked the movement speeds.

I'll finish up this test level and maybe do some texture work.

## silhouette detection and tool development

I've noticed silhouette detection being used more commonly in next generation titles. Perfect Dark Zero uses silhouette detection as a special ability of one of the guns. Here is an example (and yes, this was my camera aimed at the television :P)

PERFECT DARK ZERO - XBOX 360

What is of particular interest here is the way objects in the foreground are handled. Notice in this image how the silhouette of a spacecraft is being detected. However, foliage in the foreground is also being detected as well. I am not aware of any procedural advantage to doing this, but it certainly possible. I suppose this effect could be desirable since its primary utility in the game is to provide easier enemy recognition. I might write an additional post in the forum to see if anyone has any interesting comments on this particular technique.

The other 360 game that I noticed that will be using silhouette detection is the upcoming Ghost Recon. The game has not yet been released, but here is a quick example:

GHOST RECON - XBOX 360

---------------

Engine development has progressed since my last entry and has focused on hammering out the development tools. I now have a workable set of tools to get objects into the entry and saved into level files. One disadvantage of my current toolset is that everything is driven with keyboard commands and there is not GUI. However, since I am the programmer, artist, designer, engineer, and janitor of this project, I enjoy certain liberties. If there were others working on this project, I would wrap these tools into a QT gui.

At this point I really need a basic design document and I should try to decide upon a definite set of game features. I have done a little pre-vis and imagery that sets the mood for the title, and I have a general idea of what I want to go about developing here.

I know the title will be a 3D adventure title that will be rendered from a first person perspective. I am thinking that there will be about seven levels, each progressively larger. Dynamic lighting will play a very important role. One thing that will also play an important role will be text and inventory management. Of course, I will elaborate more on this later.

------------------

And from the gaming front, I have really spent more time with the XBox360 than I should. The achievement system is strangely addicting. Combine this with the COIN-OP classic releases available on Live and you have a dangerous mix. I have spent more time than I would like to admit playing Robotron 2084 trying to beat the high score on the in-game scoreboard to unlock the "high score" achievement. And after numerous tries and a few burst of profanity that frightened my dog, I did. Now I need to channel this Robotron energy into my work...

## Code Updates and XBox 360 Impressions

I fixed a bug that in the front/back face edge culling algorithm where the face normal was not being properly multiplied against the rotation matrix.

I added the ability to rotate or translate any selected object in the world.

I added a new red-black tree that is keyed on name (a string currently) - I have plans to key this on a 32-bit CRC-Hash in the future. I kept the red-black tree that is keyed on glname, so that objects can still be properly selected. Instancing is now properly supported.

I ported the Windows code over to Linux. I tested the code on a cluster of 15 dual-processor opteron machines with Nvidia Quadro 3000G cards connected through gig-E. I was able to render to a powerwall framebuffer of 11,520 x 3072 pixels, over 7,000,000 triangles, never falling below 35 frames per second. Very nice. I was using Chromium to kidnap and distribute the openGL state. Chromium Homepage

I added the ability to post the complete world level data to standard out. Redirecting stdout to a file will create a new instance of the modified world that can then be loaded.

I added the ability to scale any object in the world universally along all axis or independently. Before scaling can be achieved, the scaling state must be turned on (which will initialize GL_NORMALIZE). This will only be a development tool. I plan to add extra data in the world file that will track the original transformation matrix before scaling occurs and the scale factors along each axis. This will allow me to go into Maya and process the meshes correctly so that scaling can be once again turned off.

I have to confess to spending a lot of my time recently on the XBox 360. I received one over Thanksgiving unexpectedly and finally figured out how to have my N64, PS2, Xbox, and XBox 360 all hooked into my home theater receiver simultaneously.

I had tried the free XBox live trials before that came with games, but I never kept the service. I have always been hesitant to subscribe to services that automatically debit my accounts. But I found it so enjoyable this time around that I purchased a prepaid one year subscription to the service.

## Surface Latent Heat Flux in the year 2095

heatflux_2095.mpg

I've uploaded a 320x240 movie of a recent openGL application that I put together. The data shown is taken from a possible 2095 scenario that is a "worst case" possibility of atmospheric CO2 concentrations that continue to increase at an unabated rate of 1% per year. The latent heat flux field is a key field in the surface energy and moisture transfer between the ocean and the atmosphere. The warm water of the Gulf Stream provides the poleward transport of heat through ocean currents. The movie shows short time scale and small spatial features of the climate simulations by observing these instantaneous weather states.

This will be running on our R&D powerwall that we are bringing to SuperComputing 2005 this year at 6400x3200 resolution.

## success nVidia press release

http://www.nvidia.com/object/ornl_success.html

I just noticed nVidia issued a press release that involved some of my work. Must have been a slow press cycle.. :) There is a nice picture of some of the IPCC climate runs that I rendered onto the powerwall however.