• ### Blog Entries

• entries
19
14
• views
6168

Discussing my trials of creating a 3D isoengine

## A step into the past

A little off topic here... I found this poem that I wrote for my girlfriend (who is now my wife) back in 1991. Life was grand at Penn State. When I wasn't drunk I was a hopeless romantic or maybe I was a hopeless romantic when I was drunk. It all seems fuzzy now...anyway...enjoy

It is the climb
upon the steps of existence
which enfolds the ways
of ones subsistence...

As I moved through the
winding fibers of time.
Scaling the spiraling
staircase of mine.
I stopped for a moment
to ponder with the mind.
When I reach this apex,
what will I find?

I turned to continue
my ascent upon the throne,
which wound its way upward,
built of polished stone.
But there she stood,
atop the following flight.
The fairest of all maidens,
a princess showing bright.

The warm winds of beauty
that swirled from her display
wisped around the emotions
that call on Passions play.
It was these gentle winds
that led me up the stair,
to quell my inquisition
and look upon her fair.

The brilliance of her locks
Which curled in stygian hue,
brought a wave of splendor
from her eyes of deepest blue.
The softness of her face
Inlaid with velvet skin,
gave way to her sweet lips
as the parted to a grin.

Entrapment was my fate
when I looked into her eyes;
To see a mornings dawn
give birth to a sunrise.
And the gaze to which of mine
became a lasting stare,
as the streaming newborn rays
passed gently through her hair.

I took her hand in mine
and bowed to single knee,
placed my lips upon her skin
and kissed it tenderly.
The scent that laced her figure
so soft and pleasantly
was drawn from Natures flowers
and bound with Eternity.

The trembling in my body
was quieted by her hand.
but I could not come to stand.
She rose me to my feet
and caressed me with her nips.
The sweetness in her breath
then swept across my lips.

rushed through this passive form
and grasped the mangled heart
it soothed the hurt and pain.
Tindered the spiritual tourch
and brought back the dying flame.

she looked across the sky.
Nodding to falling West,
the Angel yearned to fly.
I stood there in bewilderment,
For I knew this could not be.
The setting of the fiery globe
must be deceiving me.

But where had it all gone,
the time which spans this day.
Wrapped within her loving arms
it had all but slipped away.
I knew I could not keep her,
this mistress of the light.
from Sorrows lonely plight.

Then she left my side
and rose up through the air
leaving me a tiny speck,
still standing on the stair.
It was then that I took notice,
as she was far away,

Wait! I began to utter
As I bellowed out in vain.
I cannot climb another step
without the knowledge of your name.
nothing but the silent breeze
came from the crimson sky.

I stood there on the steps,
Which was bathed in Days twilight,
and watched the triumph of the moon
as the sky gave way to Night.
With the weariness of hours
that came to pass with time.
I fell to slumber with the stars
under the grayness of their shine.

That state which overcame me
was only hours old
when it decided to release me
and let go its sleepy hold.
Slowly came my senses
as from this dormancy I crept.
I woke to the blazing sun
back from the heavens where it slept.

As the daystar, in its arc,
climbed to its pinnacle in the sky,
I began again my quest
to seek where destiny did lie.
With the renewal of my ascent
came the memory of the girl.
The one who had not spoken
yet brought hope into my world.

The image was so vivid
recreated by my desire.
Every detailed feature,
the patterned lace on her attire.
I closed my eyes to hold
the remembrance of her smile
and feeling of her touch
when I held her just a while.

The breeze around me shifted.
The daydream wavered in demise.
I was blinded by a brightness
When I lifted up my eyes.
Then it was all gone,
the light which caused the glare.
It left behind the Princess
floating just above the stair.

She drifted slowly down
so gracefully through the air.
Just the simple sight of her
and I was rescued from despair.
The joy which overcame me
pushed Silence far away
and led me to the inquiry
of what I asked just yesterday.

The beginning of her song,
the first time she sung to thee.
Where the flowing of her words
were so soft in melody.
The vowels were of the purest
as pure as sounds could be
and her name was just as lovely
when they formed, Anne Marie.

## A step into the past

A little off topic here... I found this poem that I wrote for my girlfriend (who is now my wife) back in 1991. Life was grand at Penn State. When I wasn't drunk I was a hopeless romantic or maybe I was a hopeless romantic when I was drunk. It all seems fuzzy now...anyway...enjoy.

It is the climb
upon the steps of existence
which enfolds the ways
of ones subsistence...

As I moved through the
winding fibers of time.
Scaling the spiraling
staircase of mine.
I stopped for a moment
to ponder with the mind.
When I reach this apex,
what will I find?

I turned to continue
my ascent upon the throne,
which wound its way upward,
built of polished stone.
But there she stood,
atop the following flight.
The fairest of all maidens,
a princess showing bright.

The warm winds of beauty
that swirled from her display
wisped around the emotions
that call on Passions play.
It was these gentle winds
that led me up the stair,
to quell my inquisition
and look upon her fair.

The brilliance of her locks
Which curled in stygian hue,
brought a wave of splendor
from her eyes of deepest blue.
The softness of her face
Inlaid with velvet skin,
gave way to her sweet lips
as the parted to a grin.

Entrapment was my fate
when I looked into her eyes;
To see a mornings dawn
give birth to a sunrise.
And the gaze to which of mine
became a lasting stair,
as the streaming newborn rays
passed gently through her hair.

I took her hand in mine
and bowed to single knee,
placed my lips upon her skin
and kissed it tenderly.
The scent that laced her figure
so soft and pleasantly
was drawn from Natures flowers
and bound with Eternity.

The trembling in my body
was quieted by her hand.
but I could not come to stand.
She rose me to my feet
and caressed me with her nips.
The sweetness in her breath
then swept across my lips.

rushed through this passive form
and grasped the mangled heart
it soothed the hurt and pain.
Tindered the spiritual tourch
and brought back the dying flame.

she looked across the sky.
Nodding to falling West,
the Angel yearned to fly.
I stood there in bewilderment,
For I knew this could not be.
The setting of the fiery globe
must be deceiving me.

But where had it all gone,
the time which spans this day.
Wrapped within her loving arms
it had all but slipped away.
I knew I could not keep her,
this mistress of the light.
from Sorrows lonely plight.

Then she left my side
and rose up through the air
leaving me a tiny speck,
still standing on the stair.
It was then that I took notice,
as she was far away,

Wait! I began to utter
As I bellowed out in vain.
I cannot climb another step
without the knowledge of your name.
nothing but the silent breeze
came from the crimson sky.

I stood there on the steps,
Which was bathed in Days twilight,
and watched the triumph of the moon
as the sky gave way to Night.
With the weariness of hours
that came to pass with time.
I fell to slumber with the stars
under the grayness of their shine.

That state which overcame me
was only hours old
when it decided to release me
and let its sleepy hold.
Slowly came my senses
as from this dormancy I crept.
I woke to the blazing sun
back from the heavens where it slept.

As the daystar, in its arc,
climbed to its pinnacle in the sky,
I began again my quest
to seek where destiny did lie.
With renewal of my ascent
came the memory of the girl.
The one who had not spoken
yet brought hope into my world.

The image was so vivid
recreated by my desire.
Every detailed feature,
the patterned lace on her attire.
I closed my eyes to hold
the remembrance of her smile
and feeling of her touch
when I held her just a while.

The breeze around me shifted.
The daydream wavered in demise.
I was blinded by a brightness
When I lifted up my eyes.
Then it was all gone,
the light which caused the glare.
It left behind the Princess
floating just above the stair

The unregistered version can convert no more than 5000 symbols.

## Bump!

Whoa, what happened to my journal...I walk away for 3 weeks and it gets pushed off the journal page for inactivity. I guess that is due to so many journals. I must admit with so many, it is harder to find the wheat in all the chaff.

## Back on track...

I think the icon I selected for this post sums up my progress over the past 6 weeks perfectly. With all the crap I discovered\learned about using a camera in D3D, I now have focus again and can continue where I left off...What's next. Shadows. I have been going back and forth between fixed point and precomputed and will experiment with both methods. I hear the snickers...No that won't take six weeks to work out. Six weeks may seem like a long time, but over that span I think I have only worked about 40hrs on the engine and other proofs. My personal life has been hectic and it is all I can do to get an hour here or two hours there to work on it. I hope to have screens soon showing progress.

Peace

## Pulling back on the reigns...

After spending the last month playing with a floating camera, then fixing it to specific angles and heights, I think I have decided to lock it down again and move back to a pure Orthogonal projection (actually use a floating camera with an orthogonal point of view) Why....In order to keep the scope from spiraling out of control. 2D graphics just won't cut it on a board you can freely rotate and I have neither the time nor the patience nor the skill to create models for everything I would like to have in my engine. All is not lost, I think I would like to do some sort of flight sim or FPS space shooter later on, now that I have grasped the needed concepts for making it happen. I actually wrote my own vector class and all the necessary applied matrix manipulation code. Multiplication, Subtraction, Additions, DotProduct, etc. were all needed for proper camera movement. I would also like to point out that there is just too much trig involved in it and I wouldn't have gotten far without the following texts.
Premier Press - 2004 - Mathematics for Game Developers
NAVEDTRA - 1989 - Mathematics, Trigonometry and
New Riders - 2004 - Beginning Math and Physics for Game Programmers.

All of which were good, but it would have been nice to have them all condensed into a single volume.

## Camera Revisited...

Just taking a small break from watching the monster storm hitting the Northeast this weekend. Where I am at in CT we could get 18in to 2ft of the white stuff. OK, so I playing around with my camera object and am integrating it with the engine when I take a few minutes (which turned to hours) and created a little flight simulator. This could open up some cool possibilities like flying over a map\level from the end point to where you are starting to give the player a 'quick' overview of the terrain. I think I have seen this done before but can't seem to place the game. Next up is lighting. I have been messing around with both real-time and precomputed effects and trying to weigh their strengths and weaknesses. I should have a path I am going to take after a few more proof of concepts are done.

Outta here

## Camera issues...

So what have I been doing? (...like someone would really care...) Anyway, I have been trying to get my camera to work properly. I think I have come to a crossroads however.

OK, with a camera that allows the user to 'fly' all over the place and in any direction, I think I need to throw out any possiblity of using isometric art and then go with models. I however don't want to do this. Isoart is so much easier to come across then 3D models. I have been toying with locking the camera into 3 or 4 possible angles (just to see around hills and mountains that obstruct view). Has anyone else worked something out or experimented with this. Please give me a holler if you have. I would be very interested in hearing how you handled it.

## Mountains....

It has been some time coming (and I need a little more) but the addition of mountains\hills into the engine is almost complete. I need to work out some texturing issues and add some kerneling(aka smoothing). I still have not fully recovered from my ear infection and things are generally slower (in terms of development) around the holidays. I hope to have a few screen shots soon. I have been getting some great help from VertexNormal (hey thanks Josh!) and hope to unveil something soon.

Edit #1: Added wireframe screenshot to show progress...

Edit #2: Rolling hills example (yeah, yeah, my textures have gaps in them...too lazy to fix them right now 8>) )

## Bleechhhh.

If there is one thing worse than a bug you can't squash, it's being sick for the friggen holidays! A viscious little critter bit the hell out of me and I ended up on my back for almost 3 days with some sort of inner-ear infection. I would try to sit up and the whole world would spin causing me to experience severe motion sickness (and you can guess what happens next...) I am still not totally out of the woods yet. I will try to pull my butt out of bed tomorrow to go to work. Thank God the project I am on is less than 10 miles from my house. Anyway, If I don't make it back to this journal before the holidays, I would like to wish everyone a very Merry Christmas and a Happy New Year. (Happy Hanukkah, Qwanza, etc...) Please be safe out there people....

Take Care.

## 16bit revisited

As promised, here is how I handle the 16bit translations for mousemapping. When initializing the mousemap the following call is made to determine what the color of the tile should be. In my code, I have this function overloaded (1 call for 16bit and one call for 32bit) but condensed them to show each case. See comments to follow along. The tileIndex being passed into the call is a counter which is incremented by 1 for each tile that is being processed.
Tile[0,0] tileIndex=0
Tile[0,1] tileIndex=1
Tile[9,9] tileIndex=100 and so on...

private Color GetMouseMapTileColor(int tileIndex, byte col, byte row){short red = 0;short green = 0;short blue = 0;if(_16BitColor ){// Because of the format 5-6-5 for 16bit color yields 65536 possible colors// 5 bits for red   = 32 possible variants (31 shades, 1 with no red) // 6 bits for green = 64 possible variants (63 shades, 1 with no green)// 5 bits for blue  = 32 possible variants (31 shades, 1 with no blue)//	The 65536 possible colors comes from the all the possible //      red\green\blue combinations//// This would allow for a map of size 256 x 256 if 1 color were to be used// for each tile.  I have capped the map size @ 200 x 200.  With a tile size// of 64 x 32 pixels, a map size of 12800 x 6400 pixels is possible.  I think// this is plenty big enough.  At my current scroll rate, it takes nearly// 90 seconds to scroll the width of the map.// // --- RED ---// For every 2048 tiles increment the red shade.  This is derived as follows://	Because there are a possible 32 blue shades for every green shade and a//	possible 64 green shades.  This yields 2048 possible blue\green//	combinations. The tile color is kept unique by incrementing the red//	value when these combinations are exhausted.  The 1+ is done so that //      the 0,0 tile is not completely black.  Black is reserved for anything//	off the map.  With only 32 variations of red possible a multiplier of 8 //      is used in order to map it properly into a 32bit color's value.  This//	is necessary because I am using: Color.FromArgb(red,green,blue) to//	generate the tile color. This returns a 32bit color.   red   = (short)((1+(tileIndex/2048)) * 8);		// --- GREEN ---// Because there a possible 2048 possible green\blue combinations ensure// that the green will roll over when this number of tiles (or a multiple of)// is reached.  Because there are a possible 64 green variations div this// tile by 32 (2048/32) = 64.  The multiplier is used for the proper mapping // into the call to create the tile color.   green = (short)(((tileIndex%2048)/32) * 4);  // --- BLUE ---// Because there are 32 possible blue variants ensure we roll over the value// once it reaches 32.  Again the multiplier is used for the proper mapping // into the call to create the tile color.   blue  = (short)((tileIndex%32) * 8); }else{   red = 128;   green = (short)col;   blue = (short)row;}   return Color.FromArgb(red,green,blue);}

Now, as the mouse is moving over the map, the following code is used to determine the tile the mouse is over. Note: As the color is being placed into a tile, I store off the location of the tile into an array (colorIndexToTile[]) that is indexed by the tile's tileIndex.

if( _16BitColor ){   // Get the pixel color from the mouse map surface the cursor   // is currently over (e.X and e.Y is the mouse position)   ushort[] pixel16 = (ushort[])MMBackBuffer.LockRectangle(typeof(ushort),                    new Rectangle(e.X,e.Y,1,1), LockFlags.ReadOnly, new int[]{1});   MMBackBuffer.UnlockRectangle();   // Strip out the RGB components from the returned pixel   // Anything you would want to know about how and why I do this can be found here:   // www.gamedev.net/reference/articles/article1563.asp   int red   = (pixel16[0])>>11;   int green = ((ushort)((pixel16[0]>>5)<<10))>>10;   int blue  = (ushort)(pixel16[0]<<11)>>11;   // Check to see if we are over a tile   if((red | green | blue) !=0)   {      // remove 1 from the red to compensate for it being added      // in the GetMouseMapTileColor() call      int tileIndex = (red-1)*2048 + green*32 + blue;		      newMousePosition = _colorIndexToTile[tileIndex];   }}else{   // Get the pixel color from the mouse map surface the cursor   // is currently over   int[] pixel32 = (int[])MMBackBuffer.LockRectangle(typeof(int),                 new Rectangle(e.X,e.Y,1,1), LockFlags.None, new int[]{1});   MMBackBuffer.UnlockRectangle();   c = Color.FromArgb(pixel32[0]);   // if the cursor is not over any tiles then don't do anything   // Note: the value 128 is the default set for the red component in the   //       Initialize{maptype}Map() procedures   //       A nice side effect of this short circuit is that when the mouse   //       is not over any tiles, the last tile selected remains highlighted   if(c.R == 128)      newMousePosition = new Point(c.G,c.B);}

I hope this helps. Let me know if anything is not clear or a possible better solution might exist. Again, it was something I didn't want to do (or rather didn't think about) but felt the engine should be compatible with this color depth. It was the first solution that popped into my mind.

Edit: Cut down tabs so code is at least viewable.

## 16bit Mess

All right, small rant here...

I'm bee-bopping along, working on my engine when I run another DX program which switches my color depth (but not the resolution) and didn't put it back when it exited. Talk about being rude. If you are going to write crap that does this, please return my display to its original settings...That was a major bummer. Needless to say, my mouse mapping didn't work because I have been living in a 24bit world (very naive on my part). Long story short and with almost an hour of trying to figure out why my code wasn't working, I decided to rewrite the mapping function. After a couple of days and with zero enthusiasm, I finally got it. Right now, I am just handling the 5-6-5 format but was wondering if I should also put the 5-5-5 in as well. The point being if your card supports 16bit in the 5-5-5 format, it is probably too old to handle the engine anyway. Am I wrong to think this? I am going to put everything up here and document it, to bore the hell out of some people. 8>)

One other thing, I have tried to contact VertexNormal and TANSTAAFL but with no response to emails. Tis the season to be...Jolly? Or maybe I have their wrong info.

## Engine Update

Well, I am a week into writing the terrain transition\spanning code and this is a shot of where I am at.

It is proving more difficult (actually more monotonous) than I had anticipated but the results are well worth it. On the fly calcs of a tile's neighborhood as it is being painted and the creation of lookup tables for the possible combinations is slow and prodding but I am about 85% there. Maybe another week or two. My biggest problem is just to get it down and stop tweaking it. I will have a really good cut of it and then think of a better way to do it and then spend the next night changing what was working just because it is cleaner. I have actually been spending a lot of time looking into hills & mountains. At first I was just going to have precomputed heights but VertexNormal has a really cool demo app which I have been studying and will try to emulate. His growth algorithm is amazing. I need to ping him to get some more info on how the heck he does it. My hat's off to him.

## Locking a Vertex Buffer in Managed Code

Every example I have come across seems to lock a VB in the following manner:

VB.Lock(0,0);

This returns an array (or a stream depending on the overload) of the entire buffer. This is fine and dandy for small vb's but once a threshold is reached, your performance hits a wall with a splat!

Microsoft's documentation on the subject isn't overly clear (at least it wasn't to me) so I hope to shed some light on the subject (at least on the first parameter of the following call).

public Array Lock(int offsetToLock, Type typeVertex, LockFlags flags, int[] ranks);

Microsoft's description of the first parameter is:
offsetToLock System.Int32. Offset into the vertex data to lock, in bytes. To lock the entire vertex buffer, specify 0 for both param_Int32_sizeToLock and param_Int32_offsetToLock.

In order to properly calculate the offset, you need to know how big (in bytes) the vertex structure is. This is the structure you used when creating the buffer and can be done using the Marshal.SizeOf command. (Make sure to include the using System.Runtime.InteropServices; to cut down on dereferencing)

An example of this call:
int vbStructSize = Marshal.SizeOf(typeof(CustomVertex.PositionColoredTextured));

You can also use the sizeof operator but this is an unsafe call and would require the /unsafe compiler option to be set and to be wrapped in an unsafe block.

An example of this would look like:
int vbStructSize;

unsafe
{
vbStructSize = sizeof(CustomVertex.PositionColoredTextured);
}

So now that the structure size is known, calculating the offset is done by multiplying this size by the number of vertices you want to skip over.

vbOffset = vbStructSize * 10;

CustomVertex.PositionColored[] TileVerts = (CustomVertex.PositionColored[])VB.Lock(vbOffset,typeof(CustomVertex.PositionColored), LockFlags.None,new int[]{24});

This will return a populated, single dimensioned TileVerts array of 24 elements. Don't forget to Unlock the VB as soon as you are done modifying or using it.

I hope this helps.

Well, after some tinkering I came up with a concept of spanning across like tiles. Here is a glimpse of a first cut with a before and after effect.

I am also starting to code a randomizer so long streches of beach will not look the same. (inlets, peninsulas, etc).

## The Story So Far...

I first used the KCS moniker in late 1999 while I was writing some software for Dungeons & Dragons (Yes, I was one of those junkies as well). Die rollers turned into character generators which turned into module creators which eventually spawned a map creation tool. This was near the end of 2001. My first crack at creating a mapping tool was like any other ill fated project, too ambitious with not enough knowledge and I hadn't read TANSTAAFL's illustrious book yet either. Written in VB6 at the time. Yes, yes...the snickers. When you program with something for a living 8 to 10 hours a day, you tend to use it at home as well. It was all based on GDI and was terribly slow and very awkward, and ... a failure. I shelved the project for about a year and was dabbling in DX7 & DX8, doing simple Mandelbrot's and other 'learning' stuff (while working in VC6). I read Mr. Pazera's book and pulled my old project out from the ashes. It was about this time that .Net entered the fray and I converted the ISOHex core code to C# and DX9. Although I never got everything up and running and I really wasn't interested in 2D, I learned so much about the concepts that it made the creation of my latest engine very smooth and elegant (at least I think so). I have fought more with DX9 than I have with figuring out how I should handle 3D isometric concepts. Anyway, I am going to use this journal as a place to help other people with obstacles that I have overcome (and have not!) If I can help a single person (even myself) it will have been all worthwhile.

OK, now onto the present...

My current project is aptly named Nightmare.

In the nut shell, it is a 3D isometic(ish) map generation\editing engine. I have fixed the camera height but allow rotations. The first 8 months of this year have been spent writing utilities to help make my life easier. A tileset maker, resource manager, and an alphablending application along with a first cut of the Nightmare engine.

Here are some screens of each.

An early shot of the engine putting things together...

The terrain transitions above are still a work in progess and will continue to improve. Most notably, I want to get rid of the terrain ridgedness and make it look more realistic. I am almost done doing so and will document the process once it is up and running.

## Birthcry

Hello all, I finally made the splash and became a GDNet+ member. I should have done it long ago. I just kept procrastinating. Anyway, I have been actually keeping a journal of a project I have been working on and will probably dump it here for all to see within the next couple of days. I would also like to announce my new (virtual) company. KillerCodeStudios. Yes, I have always liked that name and have now decided to make it permanent. I like the name Sir Code Alot as a handle but think that might be just a little too much over the top. Anyway, ready or not, here I am...

Len
aka Sir Code Alot 8>)