Thursday, March 31, 2011

Daily Progress

This is more of an update than a new post, but I am happy to report that I have made a lot of progress today. I feel very productive and am excited to go to class to learn about importing model fbx's into my project and converting them into binary;-) I plan on using this first for displaying my bounding spheres.

So, things that I have accomplished so far today:
  • Fixed code to calculate transformations correctly. I now create temporary transformation matrices every update and have persistent model and modelView matrices in the base object of my primitive forms' class. This means that every update, none of the transformations are incremental, but rather the matrices are reset to identity and then the desired transformation is applied. I knew that my code was hacky before, but I didn't realize the deep repercussions it could have. Keenan even mentioned that it could lead to the object exploding or twisting on itself if you let transformations increment, such as constatly changing a saved rotation matrix. Happy that this is ironed out! Tranquility in my code garden.
  • Created a sphere in Maya and saved it with tri's rather than quads. I asked Nick, a graphics guy, to do the Tri conversion for me. Then I saved it as a .fbx, ready for use in my next set of work!
  • Fixed up bounding sphere creation code. Now that the transformations are working correctly, I can actually multiply the sphere center by it's LocalToWorld matrix to transform it just like the object, and the radius by the max. absolute scale to have it encompass the object. No more weird kinks, which leads to...
  • Sphere to sphere collisions working! I tested these using printf's, visually, and in debug by checking the values.
All in all, good progress that I am very happy about.

A Light Shines Through the Weathered Boards

I had my meeting with Keenan this morning and am very happy with our discussion. He was exteremely helpful in looking at my code and explaining some of the physics to me. It turns out that the problems I am having aren't caused by what I suspected, but deeper, more foundational issues. This might sound like a discovery in the negative direction, but actually, it makes me more confident that I can make progress now. For me, understanding where the issue is is more important than fixing it by hacking and not knowing why it works now.

Anyway, the reason I decided to blog now rather than waiting until I worked today was because I want to jot down my "itinerary" of code stops that I have to make, in order to sort them all out in my head. So, here are the things that I need to fix/look at in priority order:
  • Reformat base code in Primitive Object to create transformation matrices on the fly in the update, and move persistent matrices into the model itself. The primitive object should only store the attributes, like the degrees for rotation. Like Keenan said, these are "little notecards to yourself". Ensure that this is working properly before moving on to anything else.
  • Create a low-poly sphere in Maya, and export it as an fbx as triangles (not quads).
  • Taking tonight's upcoming lecture into account, work out how to import this fbx into my code and convert it to binary data to read in the model.
  • Use this model of the sphere, or even just the verts (in this case, make a sphere model, like any of the other primitives), to draw the bounding sphere.
  • Test sphere to sphere collisions now and get them working (use printf to test).
  • Give the sphere the capability to toggle wireframe vs solid mode for visual collision check. 
So, I think that fixing the matrices is going to solve a lot of my issues, because I will then have a solid base with no hidden, hacky caveats.

Off to work on it then!

Wednesday, March 30, 2011

Pushing and Popping, Huffing and Puffing, All to No Effect

For the past several days, I have been working on fixing my sphere to sphere collisions. I kept on finding logical inconsistencies and tweaking my code, each time thinking "there's the rub! That should do it!" But, alas. Today, while debugging for the gazillionth hour and looking at my bounding spheres' centers, I noticed that they were inconsistent numerically with what they were supposed to be geometrically. I realized that I had been calculating the sphere's centers with respect to the local origin of the object rather than the world, so I fixed the problem and now the spheres' centers are correct. However, this did not fix the problem of c always being negative where


c =  distBetSpheres.dot(distBetSpheres) + sumOfRadii * sumOfRadii


GRRR!


To be honest, I also don't quite understand why I am squaring the sum of the radii. I understand how this is derived mathematically, as the orange collision book does a very good job of explaining this part, but I don't understand what this means graphically. I fully intend to ask Keenan tomorrow during our morning meeting.


It turns out that the radii squared are always significantly larger than the magnitude of the vector between the spheres squared, and I don't know why. This frustrates me to no end, especially considering that it's probably an issue that's really simple and that I am overlooking, and when pointed out to me, will make me feel like I do not belong in this field, yet again. Don't get me wrong, I love it. I just really don't want to end up shooting myself in the foot here. 


In order to debug this better visually, I decided to represent the bounding spheres as wire glut spheres while the objects are not colliding, and solid spheres when they are. Also, I was beginning to doubt the legitimacy of the math in my function, namely the c being ridonkulous (I know it's not the c's fault, I reckon it has to do with 2 different scales between the radii and the world coordinate system, or something really obscure). In order to move the process of testing along, I wrote another, simpler function for detecting sphere collisions. This one does not return t for the time of collision, but just returns true or false. All that I do is check if the sum of the radii of the spheres is >= to the distance between their centers. I then set whether they are colliding accordingly. 


Two issues immediately cropped up. 

  1. A collision is detected very early. Mathematically, it makes sense as the numbers work out. Graphically, it makes no sense as the spheres are nowhere near touching. This means that something about my radii or sphere center calculations is off. What though? If I fix it, it should also fix the function that returns t and then c won't be all wonky!
  2. The glutSpheres for both my cube and pyramid were drawn on top of the pyramid. So, on the screen, I had a lonely little cube with no bounding sphere floating around, and a spinning green pyramid flying across the screen, hogging both bounding spheres. I encapsulated each sphere creation call in glPushMatrix() and glPopMatrix(). I tried calling glTranslatef. Nothing. I even passed ridiculously large values to glTranslatef and yet there it still was, a green pyramid, with two spheres floating around it. This leads me to conclude that the glColor* issue that I had mentioned in my previous post is related to this, that any gl* calls that I make have no effect. I wonder why this is happening. I suspect that it could have to do with the fact that they are somehow being overridden by my other actions, or because I haven't been using glPush and Pop so far, resorting to my own matrices. I don't know enough about OpenGL to know if it has any special idiosyncrasies that I might be missing, or neglecting to respect.  Nonetheless, it is a frustrating conundrum that I plan on resolving tomorrow at the Keenan meeting.
So now, I can report that even though my graphical results look much worse than before, I am actually mathematically closer to having the problem solved. At least I know the issues now.

Friday, March 25, 2011

Colors and Textures

Spent about 6-7 hours today trying to figure out why my glutWireSphere wouldn't draw in a color other than black. The ultimate goal behind changing the color of the sphere is to have the wire spheres (which represent the bounding spheres of the primitive objects inside them) be blue when they are moving around and not colliding, and turning green when they are colliding. In order to test the waters for how to change the color though, I first decided to manually set all of the spheres around cubes to be red. Initially, I expected it to be as simple as writing:


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


before calling glutWireSphere. However, when that didn't work, I began to try all sorts of things. I had started out by placing the sphere code in the cube's draw function, which is where I was first binding the vao of the cube model to the cube object. I moved these calls outside, into the form manager. This did not yield any progress. I then tried wrapping the calls in glPushMatrix() and glPopMatrix(), glBegin(GL_LINES) and glEnd(), and combinations of both.


At this point, I was quite frustrated and decided to see if it was a driver or machine problem that I was experiencing. I sent my project to my friend Jeff, and asked him to run it to see if he also saw black spheres. Surprisingly (because I didn't really expect to be right about this), he reported that the spheres were the same color (texture really) as the cubes that they encompassed. To test this theory further, he changed the call to glutWireSphere to be glutSolidSphere, and indeed, the screenshot he sent me displayed a swirly ball of sandy-stone color.


This was now doubly frustrating, because not only was the glColor* not having the desired effect, but I also couldn't test other ideas since I was still only seeing black. I have yet to figure out what about my machine makes it different, but I am very determined to do so.


I began to scour online forums, graphics sites, and all of my textbooks to see why my call to glColor* was being ignored. I even went so far as to change the glColor3f call to 4f, and then 3ub, thinking that maybe I was crazy and missing something very obvious. None of this helped. However, I did come across some interesting new information, which although it didn't solve my problem, taught me some useful facts.


First of all, it appears that when lighting is used, calls to glColor* will have no effect unless glEnable(GL_MATERIAL_COLOR) is called. Now, I am still unclear as to by lighting, they mean the specific call of glEnable(GL_LIGHTING) or just having lighting in general. I am still very new with lighting details, and never really learned about lighting beyond a very basic overview of types in a Graphics class, so forgive me if this is obvious. However, I checked my entire solution and did not find any calls to glEnable(GL_LIGHTING), so as a result, I still don't know if this applies in my case. Either way, I tried it to make sure, and, it did not help.


I then read that blending will happen if glColor* is called after a texture is bound. As one person explained it on a forum, OpenGL is a state machine of sorts, and once you put it in one state, it will not change until you tell it to do so. This is the case with all programming really. We programmers bitch all the time about the program not doing what we want, but we're the ones telling it to do the wrong thing, or not telling it to do the right thing. Any who, back on track. So, apparently, the blending is what was occurring as far as I could deduce from the screenshot that Jeff sent me. Calling glColor* would blend with the texture, or "tint" it to be the selected color in other words. In order to prevent this, I tried calling glDisable(GL_TEXTURE_2D) and glEnableTexture(GL_TEXTURE_2D, 0). The latter is being passed a null parameter for the texture id in order to clear the buffer, so to speak. Neither of these seemed to have any effect, not alone and not in combination.


At this point, I was once again at my wit's end-- a phrase I seem to be using commonly nowadays when I'm programming. I emailed Keenan and told him about my problem, and he suggested that it might be a shader issue-- something that I had not considered at all until then. For some reason, I had thought the shader and the  calls to the glColor* for glutWireSphere to be entirely separate from each other. After emailing Keenan though, he assured me that we would discuss the shader further next week to get it working, and that in the meantime, I could print to console when the objects were colliding. 


This brings me to another "discovery" that I made today, or rather, a realization. Looking at my sphereToSphere collision code, I realized that the velocity vectors v0 and v1 for each object that I was passing, were completely wrong. Rather than representing the object's actual velocities, I was passing in their translations. This is ridonkulous, and not what I had intended but after programming for a long time that night, I must have had a brain fart. I now know that I need to go back into my code and create actual velocity vectors for each object. Right now, the two objects that I have on screen do not even have any linear velocity, just rotational, because they are turning about their own axes. Overall, this means that even without colors and print statements, I already know that my sphereToSphere collision calculations are wrong because they are based on some ridiculousness that needs to be fixed to non-ridiculousness.


That is all that I have to update right. Hopefully, I will have some great progress to post about tomorrow!

Thursday, March 24, 2011

Bounding my Frustrations with Spheres

It's been quite a while since my last entry, but I have been very busy at work on my engine. Soon after posting my first few entries, I got stuck. I didn't have a clear and detailed plan, just large general milestones. Having never taken on a project of this caliber before, I didn't know where to start. Having modularized several code examples from the SuperBible, I did not know where to go from there. After speaking to Keenan, I learned that it was much better to use Vertex Buffer Objects rather than GLBatches. However, I still did not understand how to implement them just from reading the book, and my progress dwindled to a standstill. I didn't even make any videos by this point because I kept deleting the code that I had written because I was happy with it. Nothing felt like an achievement because it wasn't "amazing", even though I knew that I was learning a lot even in making small examples.


Then, as we began to work on a Graphics System in my Engine class, I began to understand how a Graphics system should be structured. Little by little, I began to tweak my system. It was lucky that I could work on my projects in parallel for both Engine and my Independent Study, because it allowed me to really focus on the system and understand the details better. At this point, I was rushing to get more and more implemented in an increasingly shorter amount of time. I didn't think that videos and blogging were a priority in the precious time I had left. 


Looking back on it now, I realize that taking 15 minutes out of my day wouldn't have harmed anything, but probably only helped to straighten out my thoughts and chronicle my difficulties. I suppose that now, I am coming to terms with the fact that progress isn't only about success. If it were, then it wouldn't be progress because there would be no journey up as everything would come on the first shot. Instead, progress is at its best when challenges are overcome. That is why I am going to focus on chronicling my process now, to see how much I have achieved and grown by the time Spring quarter ends.


By the end of the Winter quarter, I was still behind in terms of my original milestones for the Indie Study, but my system was coming along-- it just took me a little longer than I expected to get there. Then again, that is the story of my life- underestimating how much time things will take. From now on, I am going to make a significant effort to work on things more consistently and thoroughly throughout, rather than at medium speed with high interval bursts.


So right now, it is Spring Break, and my goal is to have sphere to sphere and cube to cube collisions implemented by the time it is over (3/28). This leaves me with a little less than 5 days. I know that I can do this. Although I really got stuck this week and was at my wit's end, after speaking to Keenan, I realized that he was right. I do need to calm down and recognize that I already learned this stuff, and though I may not have applied all of it before, I am prepared to do so. 


After reading a ton of material on bounding volumes over the past several days, I finally got my bounding spheres to work last night. I used an older function that I had written in Physics class for creating a bounding sphere, and integrated this into my current code. Following this, I implemented frustum culling. At first, I was really confused about how to do this, but then Keenan reminded me about the camera lecture that we had where he had discussed point distance to plane determination, and this was really helpful. A lot of things came back to me when I watched this lecture. I realized that I already know and understand a lot of this, but I can't always pull it out of my head since there is so much. That is another skill that I need to improve upon: knowing when to apply what knowledge. 


I also implemented the drawing of glut wire spheres with the parameters of the forms' bounding spheres so that I can actually see the bounding volumes in debug mode. This is really helpful for determining what is happening, and is necessary for my collision tests. For the collisions, I plan to have the wire volumes to be green when they are not colliding, and turn blue when they are to indicate the collision. This also really cheered me up because I got to see my progress, literally. So far, I have the bounding spheres implemented for my cubes and pyramids.


Goals for Today/Tonight:

  • Re-read orange collision book chapter 5 to refresh intersection tests
  • Create progress video to show wire bounding spheres and discuss frustum culling
  • Post video on the Wiki
  • Give the sphere to sphere collision implementation a go