Monday, August 20, 2012

3D Math Primer for Graphics and Game Development, 2nd Edition

I've picked up a copy of 3D Math Primer on Graphics and Game Development recently and have been slowly going through it.  It's been around 15 years since I took Linear Algebra, or had to do any real matrix or vector based math, so the brain cells are slowly being re-initialized.  Heh.  Hopefully, this turns into a series of posts to share as I relearn things cruising through the book.

Here's what I've covered so far.

Chapter 1 deals with coordinate systems and concepts.  I was always fairly decent at trig so this went by really quick.  Chapter 2 gets into vectors and discusses the importance of the dot and cross products.  I remember learning and using these in school, but their application in game development terms wasn't obvious to me.  There are a couple of really good exercises that hit home the importance of these two operations.

One of the exercises describes an NPC in a game at a point p, that has a forward vector v.  Given this, and a point x, how can you use a dot product for determining whether or not the point x is in front or behind the NPC?

There are a couple of things to know about the dot product.  First, it gives you a scalar.  Big whoop.  How can this be used?  Well, the sign of the scalar gives you an indication of the relative direction / angle between one vector and another.  If the dot product is positive, then the angle between them is between 0 and 90 degrees.  If the dot product is 0, then the vectors are orthogonal (ie. at right angles).  If the dot product is < 0, then the angle between the vectors is greater than 90 degrees (and less than 180).

So, given a NPC location of p, we can calculate a vector x-p that gives us a vector describing the relative position of point x from point p.  If we know the facing of the character (vector v at point p), then we can take the dot product between v and x-p and know the relative positioning.

Recall that the dot product yields a scalar, defined as:

a dot  b =
(ax*bx + ay*by + az*bz).

Given this, we can determine if point x is in front-of or behind the NPC:

If vx*(xx-px)+vy*(xy-py)+vz*(xz-pz) > 0, it's in front.  If it's < 0, is behind.  If it's == 0, then it's to the side of the NPC.

Cool!

Using the magnitudes of the related vectors and the relation: cos theta = a dot b / (||a|| * ||b||), we can further determine the angle between the two vectors.

Another cool exercise from the book details the practical application of the cross-product.  If the NPC above navigates from point p to point q and then to point r in the x-z plane (using left hand orientation), how can we use a cross-product to determine if the NPC should turn clockwise or counter-clockwise at point q in order to reach r?

Recall that the cross-product yields a new vector, defined as:
a x b =
[ax ay az] x [bx by bz] =
[ay*bz-az*by -(ax*bz-az*bx) ax*by-bx*by]

Here, it helps to know that the cross-product for a couple of vectors yields another vector that is orthogonal to the other two vectors.  This vector gives a magnitude that is proportional to the area of the parallelogram area formed by the vector sides.  We can look at the direction of the vector to clue us in to whether the orientation from one vector to another is clockwise or counter-clockwise.  If the angle from a to b is less than 180 degrees, the resulting vector will point up (left-hand rule orientation) on the orientation is considered clockwise.  If the angle from a to b is greater than 180 degrees (ie.  from b to a is less then 180 degrees), the orientation is considered counter-clockwise and the resulting vector will point down.

In the NPC case above, it's pretty straightforward to calculate the cross-product.  Doing this results in a single vector that either points in the +y direction, or the -y direction. Using this info, we can easily determine which way to rotate the NPC at the point q.  The NPC could actually rotate either way and still reach the same position.  The cross-product ends up giving you the shortest direction to rotate through.

Cool x2!


PDF Xchange Viewer Fu

I do a lot of PDF technical document reading where I'm constantly flipping back and forth between  various document sections.  Although my favorite PDF viewer of choice, PDF XChange Viewer, rocks the house for annotating, searching, saving, etc., it sucks when it comes to intra-document navigation.  It's got bookmarks and capabilities to run multiple instances, but I haven't liked the navigation these implement.  I've also tried using multiple copies of my documents and gotten that to work the way I liked (ie. tabbed document browsing), but having multiple copies seems like a real waste to me.

Enter Chrome.

Using Chrome tabs, you can easily and quickly open up multiple instances of a document by using the address bar to navigate to the local file.  From there, just right-click and select duplicate. You end up creating multiple instances of PDF XChange Viewer in this case, but the navigation is SOOOO much better than clicking on the Windows taskbar.

You may have to disable the built-in PDF Viewer in Chrome to get PDF XChange Viewer working.  To do this, enter "chrome://plugins" and simply disable "Chrome PDF Viewer".

QED.

Sunday, May 6, 2012

SVN -> Mercurial mirroring

I'm continuing to use libgdx for my game development.  However, locally I'm using Mercurial for software configuration while libgdx is currently stored up on GoogleCode using SVN.  Ugh.  How to stay in sync or otherwise mirror the SVN repo?  So far, I've been maintaining things manually.  The approach I take for pulling in SVN updates is outlined on the Selenic site here:

http://mercurial.selenic.com/wiki/SubversionToMercurialHowto

This boils down to keeping a single directory that serves both as a SVN *and* Hg working directory.  From this directory, I do a clone per project to set things up.  For example, I have a clone of libgdx for my MatchCard game, another clone for Doodle Bug, another clone for Pyromancer's Laboratory, and yet another one for DB42 and DB42Lite.

The nasty part of this business is that means I have to go to my local SVN repo, perform an SVN update, and then do an add/remove/commit on the Hg repo.  Since this is a manual operation, it doesn't happen all that often.  I'm between games right now and wanted to more or less set things straight in terms of keeping in sync without having to rely on a manual process.  Here's the solution I came up with:

1) I'm sticking with the shared SVN / Hg working directory.  This is really straightforward and I have my brain completely wrapped around what's going on.

2) I've got cygwin installed on my Win7 x64 workstation to give me all the great tools that Unix developers know and love... grep, head, tail, bash scripting, etc.

3) I've got Jenkins installed on this same machine.  This does periodic job runs that query the state of the SVN repo, pull in new updates, and then add/remove/commit those changes to the Hg side of the shared directory.  The build trigger is simply "Build Periodically" that runs the following script:

for ((COUNT=`svn log -r base:head | grep -E "^r[0-9].*" | wc -l`; COUNT > 1; COUNT-- ))
do
   GETREV=`svn log -r base:head -l 2 | grep -E "^r[0-9].*" | tail -n1`
   TOKENS=( $GETREV )
   REV=${TOKENS[0]}
   AUTHOR=${TOKENS[2]}
   COMMENT=`svn log -r $REV | tail -n +4 | head -n-1`
   CHECKINCOMMENT=$(echo -e "$COMMENT\nSVN $REV")
   svn update -r $REV
   hg addremove
   hg ci -u "$AUTHOR" -m "$CHECKINCOMMENT"
done
What this script does is read the number of changes between the local base and the GoogleCode head.  If it is > 1 (ie. there are new changes), it iteratively pulls each SVN changeset and then commits those to the Hg repo using SVN revision, author, and comment info pulled from SVN's log command.  This took a while to get going -- my bash scripting skills are extremely rusty.

The one thing I'm lacking at this point is an "hg push" up to a default repo out on the Intertubes.  I have it in mind to share the repo on Assembla, but I currently don't have the libgdx's team blessing to do this (yet) and I also have a support request into the Assembla team to see if they have any server side tools that might accomplish the same thing I'm doing locally.  This whole process is highly reliant on my build server not dying.  If I could push those operations out to some other server, that'd be better in the long run.  For now, though, it works

Hope this helps someone trying to accomplish something similar.

Friday, December 9, 2011

Andronavi post

I think this explains the high number of Japanese folks playing the game:

http://andronavi.com/2011/12/144583

Google Chrome butchers it in translation I'm sure.  I can't tell if the reviewer liked it or not.

Tuesday, December 6, 2011

Current standings

Here are the current standings of DB42 in the various markets.  China has got some huge growth going on.  Cool stuff.

Market Name

Upload Date

Publish Date

Downloads

Current Rating (# reviews)

Notes

Android Market

11/27/2011

11/27/2011

813 (324 active)

5/5 (2)



SlideMe

12/4/2011

12/4/2011

287

none yet



AppChina

12/4/2011

12/5/2011

507

none yet



Mobango

12/4/2011

12/6/2011

0

4/5 (1)

There's one review, but the download count is currently 0.  Curious.

Amazon App Store

12/4/2011

Still Waiting







Sunday, December 4, 2011

More alternatives

Uploaded DB42 to Mobango and Amazon.  I said i wasn't going to upload it to Amazon... but since I'm doing the lite version I don't think it counts. ;)

I understand the wait to get something published on Amazon is on the order of a couple weeks.  We'll see if it is up there by mid-December.

Mobango requires a review before an app is published so I'm waiting on that.  On AppChina, my app has entered the 'audit' state, whatever that means.  Hope it is accepted!

Saturday, December 3, 2011

Alternative Android Markets

Taking a tip from Neil Rajah and his blog (Ziggy's Games), I've gone ahead and added DB42 to a couple of new markets: AppChina and SlideMe.  I registered the game on AppChina about an hour ago and am still waiting for it to be approved.  *HOPEFULLY* Google translate didn't totally slaughter the simple descriptions I put in.  I figure the simpler they were, the less likely the translation would be something weird for a Chinese person to understand.  On the flip side, I've fired off an e-mail to a former co-worker of mine that knows Chinese.  Hopefully he can help me round things out.

I registered the app about 5 minutes ago on SlideMe.  It also requires a pre-approval process, but I just got an indication as I was typing up this blog post that it has been published.  We'll see how things go!!!