Search Unity

After playing minecraft...

Discussion in 'General Discussion' started by jc_lvngstn, Oct 8, 2010.

Thread Status:
Not open for further replies.
  1. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    The idea of distribution of light is simple, but there are some pitfalls:

    1. If you remove the light source (remove the actual source or just add a cube somewhere), you have to clear and recalculate light for the chunk you changed and some or all its neighbour chunks.

    2. As chunks affect each other, and you can't calculate light correctly for the chunks that are on the current edge of the map. For example, you can't do correct lighting for the northest chunk (#1) because its northern neighbour (#2) doesn't exist on the map yet. And if the player goes north and the chunk #2 appears on the map, the lighting of chunk #1 should be recalculated.
     
    Last edited: Jul 14, 2011
  2. vesuvias

    vesuvias

    Joined:
    Dec 14, 2009
    Posts:
    31
    Lighting is one of those things I haven't fully figured out myself yet. Ultimately I don't think it can be done perfectly in real-time. Now when I say that I mean baked texture type lighting where we bake shadows into the mesh somehow (I do it by using the the Color attribute of a vertex, which is used by a shader when the texture is finally rendered). Dynamic lighting still works on top of this but its flawed as we know (goes through walls, etc).

    I calculate lighting when I generate my chunk (mine are 16x16x16) and I have huge problems across chunk lines because of this. I know how to fix it, its just a lot of work. You basically would need two passes on chunk generation. One that generated geometry minus lighting and then another pass that generates lighting. The problem being that for a lighting pass you must have generated all of 26 chunks of geometry that surround the chunk that you want to generate lighting from to be completely accurate (think a cube at the center of a 3x3x3 cube volume).

    You can see the problems I have across chunk lines because of pretty clearly here:




    Note: I am not using the code mentioned earlier here (I rolled my own) and yes I do support sloped terrain. And yes my texture use is headache inducing :).
     
  3. Manmax75

    Manmax75

    Joined:
    Jun 13, 2011
    Posts:
    88
    What if you run light calculation on a separate thread. When you recalculate the light for the chunk, make the neighboring chunks recalculate as well, however, stop recalculating if that neighboring chunk is in the correct light level of the current chunks border or if no chunk exists yet. I would assume this is how it is done in minecraft. If you ever watch a sunset/sunrise in minecraft you will notice lightning will be done in chunks, and will span your entire render distance. Then when you move to any new chunks that are rendered firstly the global light is applied(sun and shadow) and then item light is added(torches, etc).

    I am using raycasts, but I am still working out how to do block placing :|
     
  4. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    I have done final light smoothing as described here. The funny thing about it is that it gives you ambient occlusion absolutely free. It's not the real SSAO, but looks almost the same. Here are some videos of that guy's engine: http://www.youtube.com/user/Slaihne12

    And here are my screenshots:
    $x.jpg $x2.jpg
     
    Last edited: Jul 17, 2011
  5. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    Some more screens
    $3d-noise.jpg $3d-noise-3.jpg $3d-noise-2.jpg

    3D noise is impressive.
     
  6. Joel-Santos

    Joel-Santos

    Joined:
    Feb 23, 2010
    Posts:
    121
    Just... Beautiful! <3
     
  7. Manmax75

    Manmax75

    Joined:
    Jun 13, 2011
    Posts:
    88
    Very, very nice. Thanks for the link, I will use that method. How fast is your 3D noise Alex. And is it Perlin or Simplex?
     
    Last edited: Jul 17, 2011
  8. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    I use simplex noise just for one simple reason: some time ago I was trying to make a seamless/tileable 2d-noise which can easily be done from regular 4d-noise. So, I was looking for any source of 4d-noise, and the only source I found was one of the simplex noise. Then I made a little noise library and stuck with it.

    The speed greatly depends on how many noise octaves you use:

    16x16x128 chunks, 4 octaves of 3d-noise ― 35..45ms
    16x16x128 chunks, 2 octaves ― 20..25ms
    32x32x128 chunks, 4 octaves ― 170..210ms
    32x32x128 chunks, 2 octaves ― 90..110ms

    ---
    I'm thinking on how to improve lighting. The current problem is that if there is a large obstacle for sun light, even if it's very, very high, it becomes too dark on the ground, because the sun light goes straight down and doesn't spread in horizontal direction. Another situation: there's a hole in the roof that lights up only a small spot on the ground, everything a bit farther remains very dark.

    $d2.jpg
     
    Last edited: Jul 17, 2011
  9. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Given the complete square grid nature of minecraft, why would you bother using physx? rolling your own simple collisions are going to be the done thing, and far faster. They are grid squares. The physics involved are insanely simple. Everything is just a square.

    Now lets assume you dont want to. Then its also OK to create 128 physx colliders and just shuffle the ones that aren't used (with rigid bodies + kinematic of course) and move them to surround the player's area.

    You only need 18 in a worst-case scenario so 128 are fine. You move them ahead of where you go.

    Creating collision meshes on the fly is also fairly ok. You would want to break up the meshes you combine into cells of say 8x8 blocks instead, each with a game object and its own optimised collisions via box collisions and compound objects (its just plain faster than mesh).

    Not sure why people keep going the mesh collider route, its suicide on the framerate and no point, your worlds are made of square bricks for gods sake.

    So either pool a bunch of box colliders and shuffle them where they're needed to be, or make your own collisions (I'd make my own).
     
    Last edited: Jul 17, 2011
  10. Manmax75

    Manmax75

    Joined:
    Jun 13, 2011
    Posts:
    88
    Alex, with your lighting; perhaps making the lowest light level not so dark? I mean minecraft isn't necessarily pitch black.
     
  11. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    hippocoder, personally I stick with PhysiX because I plan to use real physics later, falling blocks or maybe even falling constructions. For example, if we remove the red block, some other block on the left should break and the whole long thing should fall down.

    $a.jpg

    On the one hand
    a) Calculations must be relatively simple; because all we have is just huge square blocks, everything consists of huge square blocks.
    b) Weights, stresses, etc can be precalculated and saved on disk on map generation stage. I can sacrifice the unlimited, generated on the fly world.
    c) Even if additional calculations can not be done in real-time, the reaction on player's actions shouldn't be necessarily instant, some delay is acceptable.

    On the other hand I have a trouble. I don't know where to start from.
    :)
     
  12. Manmax75

    Manmax75

    Joined:
    Jun 13, 2011
    Posts:
    88
    Alex can I have a link to the noise you used? Also with your physics. Are you going to go about like minecraft physics with sand and gravel. Or real physics? If you go about real physics your going to run into the problem of how the blocks interact with your "grid". I.e, a block will be half way in between a grid space and another, or between chunks, etc. This is where you may run into lighting and issues with your code. Perhaps make it so if a collapse is going to happen. Quickly instantiate all effect-able cubes, delete the original terrain. Then have this new entity as a physics entity which is then affected by physics. Each cube can be a separate physics entity but constrained to a neighboring effect-able block.
     
  13. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    I've attached my noise sources, there are several files there;

    NoiseBase.cs ― abstract class, declares public methods for getting noise values and creating 2d-arrays filled with different types of noise.
    SimplexNoise.cs ― simplex noise implementation, inherits all methods from NoiseBase. It's the general purpose class to use in your programs.
    ChunkNoise.cs ― a class that derives from SimplexNoise. Adds some helper methods to fill chunks with noise. Wx, wy, and wz are coordinates of blocks, cx and cz are coordinates of chunks.

    Editor/NoiseGenerator.cs ― a GUI that allows you to experiment with simplex noise settings and see what the result looks like. Isn't finished yet, but at least you can see the noise and save it as .PNG.

    ---
    > Are you going to go about like minecraft physics with sand and gravel. Or real physics?

    As for sand and gravel I don't know yet. I want to use real physics basically for construction destructions. I really don't like those crazy and impossible installations that some people erect in Minecraft.

    > If you go about real physics your going to run into the problem of how the blocks interact with your "grid". I.e, a block will be half way in between a grid space and another, or between chunks, etc.

    I see it this way:
    For example, the player removes a block that holds, let's say, a part of the roof of that player's house. The part of the roof becomes an independent game object with its collider, rigidbody, etc. It falls down. When it hits the ground or some other obstacle, it splits into a set of independent cubes that can be collected like ordinary in-grid blocks.

    The current problem is that I can't figure out what exact "part of the roof" should fall and in what conditions. I know nothing about strength of materials and don't know yet how to calculate tensions, forces, etc inside/between blocks. Maybe I should invent my own simplified system just like the lighting in Minecraft.
     

    Attached Files:

    Last edited: Jul 19, 2011
  14. Manmax75

    Manmax75

    Joined:
    Jun 13, 2011
    Posts:
    88
    Thankyou, I am using Beezir's example, I must be totally blind or maybe its because I am half asleep. But I can't seem to find where his code interacts and actually generates the terrain from the noise. I have been scouring through Terrain-Brain I just can't see it.

    Now with your predicament, I really primitive beginning could be; say you have a platform and you destroy the block holding it up. So now you have a floating platform. What you could do is, every time a block is destroyed run a check to see if that block and its adjacent block is connected to ground(This can be very computationally expensive, because it can be checking massive amounts of blocks, unless you add a limit. So it will stop checking after 20 blocks away from origin, or something.) once you have determined what blocks are airborne, turn it into a independent gameobject with its collides, etc. Each block will have its own physics entity and then constrain them to their neighboring blocks. Then add weight depending on what type of block was originally there.I.e the stone end of the platform will fall first or possibly the constraints with the other blocks will fail, and mark part of the roof break and fall separately, etc.
     
  15. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    Is there a way to say to scene view shader to use vertex colors?
     
  16. Manmax75

    Manmax75

    Joined:
    Jun 13, 2011
    Posts:
    88
    What?

    Also, I think it is the getTerrainDensity function that help determine the terrain.
     
  17. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    Sorry, I mean that the shader that Unity uses to show the scene in the scene window doesn't use vertex colors. In the game window everything looks fine, but in the scene window all cubes are unlit. Is there any way to modify the shader that is used in scene window?
     
  18. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    Yes
    Edit->Project Settings->Quality
    Editor Quality
     
  19. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    Solved. Rendering path in Player settings was set to Vertex Lit. I switched it to Forward and the scene view became as nice as the game view.
     
  20. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    Two news:

    1. I found a simple way to generate canyons that look good from a distance and from nearby.

    $g.jpg

    Code (csharp):
    1. var value = noise.GetValue3D(x, y, z, octaves: 6, startFrequency: .05f, startAmplitude: 1);
    2. if (Mathf.RoundToInt(value * 8) % 2 == 0)
    3. {
    4.     blocks[x, y, z] = Block.Stone;
    5. }
    6. else
    7. {
    8.     blocks[x, y, z] = Block.Empty;
    9. }
    2. I made my shader to calculate UVs on the fly from vertex x,y,z-coordinates. This makes it possible to project one large texture onto multiple blocks by changing texture's Tiling property from 1 to 0.5 or 0.25.
    $h.jpg

    Here is the pseudo-code:
    Code (csharp):
    1. float wx = worldPosition.x;
    2. float wy = worldPosition.y;
    3. float wz = worldPosition.z;
    4.  
    5. float nx = faceNormal.x;
    6. float ny = faceNormal.y;
    7. float nz = faceNormal.z;
    8.  
    9. float u = wy * nx + wx * (ny + nz);
    10. float v = wz * (nx + ny) + wy * nz;
     
  21. Manmax75

    Manmax75

    Joined:
    Jun 13, 2011
    Posts:
    88
    Very nice. Is your world Infinite, or?
     
  22. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    At this very moment yes, it is theoretically infinite. Practically the game crushes after a while, because I don't destroy old chunks.
     
  23. Manmax75

    Manmax75

    Joined:
    Jun 13, 2011
    Posts:
    88
    Oh yes, Also with the noise you gave me, what function should I use to generate the noise for each chunk.
     
  24. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    The most useful are chunkNoise.FillMap2D and .GetValue3D. I wrote an example:

    Code (csharp):
    1. public static Block[, ,] CreateLandscape(int chunkX, int chunkZ)
    2. {
    3.     Block[, ,] blocks = new Block[Settings.CHUNK_SIZE, Settings.WORLD_HEIGHT, Settings.CHUNK_SIZE];
    4.     ChunkNoise noise = new ChunkNoise(seed: 12345);
    5.  
    6.     // Calculate heightmap
    7.     float[,] heightmap = new float[Settings.CHUNK_SIZE, Settings.CHUNK_SIZE];
    8.     noise.FillMap2D(heightmap, chunkX, chunkZ, octaves: 5, startFrequency: .03f, startAmplitude: 5);
    9.  
    10.     // Fill chunk with blocks
    11.     for (int localX = 0; localX < Settings.CHUNK_SIZE; localX++)
    12.     {
    13.         for (int localZ = 0; localZ < Settings.CHUNK_SIZE; localZ++)
    14.         {
    15.             // Create ground
    16.             int height = Mathf.RoundToInt(Settings.SEA_LEVEL + heightmap[localX, localZ]);
    17.  
    18.             for (int y = 0; y < height; y++)
    19.             {
    20.                 blocks[localX, y, localZ] = Block.Stone;
    21.             }
    22.  
    23.             // Create mountains
    24.             int worldX = localX + chunkX * Settings.CHUNK_SIZE;
    25.             int worldZ = localZ + chunkZ * Settings.CHUNK_SIZE;
    26.  
    27.             for (int y = height; y < Settings.WORLD_HEIGHT; y++)
    28.             {
    29.                 float noiseValue3D = noise.GetValue3D(worldX, y, worldZ, octaves: 6, startFrequency: .05f, startAmplitude: 1);
    30.                 if (noiseValue3D > 0)
    31.                 {
    32.                     blocks[localX, y, localZ] = Block.Sand;
    33.                 }
    34.                 else
    35.                 {
    36.                     blocks[localX, y, localZ] = Block.Empty;
    37.                 }
    38.             }
    39.         }
    40.     }
    41.  
    42.     return blocks;
    43. }
    44.  
    The same code at PasteBin.

    In my case
    Settings.CHUNK_SIZE = 16
    Settings.WORLD_HEIGHT = 128
    Settings.SEA_LEVEL = 40
     
    Last edited: Jul 21, 2011
  25. Gigiwoo

    Gigiwoo

    Joined:
    Mar 16, 2011
    Posts:
    2,981
    Heya,

    What you are doing looks absolutely fantastic. Because I'm lazy (400 messages to read - egads!), is this project open source? Are you collaborating with the community? I see code snippets on some of the sections and am trying to figure out if the project is available for download somewhere.

    Sorry to ask what is probably been answered already.

    Gigiwoo.
     
  26. Manmax75

    Manmax75

    Joined:
    Jun 13, 2011
    Posts:
    88
    We are all sort of doing our own projects. You can check out a really basic start with Beezirs code, I think on the first page. And then jv-lvgston's version which is much more developer. On, I think, the 2,3 or 4th last page
     
  27. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    There is a problem with transparent blocks. Normally meshes with transparency are sorted and then rendered, but in our case most of transparent blocks are part of the same mesh. Therefore the blocks cann't be sorted, and if the mesh overlaps itself we see artifacts:

    $i.JPG

    There are also artifacts at the edges of different meshes:
    $j.JPG $k.JPG
     
    Last edited: Jul 24, 2011
  28. macdude2

    macdude2

    Joined:
    Sep 22, 2010
    Posts:
    686
    I was just wondering how you were able to build the terrain? That ability would be extremely useful not only for mine craft, but also for level creators.
     
  29. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    macdude2, just spend a day playing with 2d- and 3d-noise and you'll get the idea.
     
  30. Manmax75

    Manmax75

    Joined:
    Jun 13, 2011
    Posts:
    88
    macdude2, let me give you a quick run through. Lets say the world is generated in "chunks" each chunk is filled with noise data to see what block should be there. The data is then handed to a builder which generates the mesh and renders the blocks.
     
  31. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    I'm experimenting with color light sources. Still in progress, but looks nice already.

    $l.JPG $m.JPG

    There's no sunlight on these screens, it's switched off for a while.
     
  32. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
  33. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
  34. Mark-Davis

    Mark-Davis

    Joined:
    Jun 21, 2011
    Posts:
    156
  35. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    In order to check bottlenecks and increase performance I moved almost all my code that doesn't touch Unity classes into a separate library to profile it using native .Net tools. What I saw surprised me in a bad way ― my code runs several times faster using .net compiler than using mono.

    $Captura.JPG

    This table shows the total time in milliseconds that different stages of creating the chunks take.

    Terrain ― filling chunks with different types of blocks.
    Basic lighting ― adding sunlight.
    Complex lighting ― adding light from neighbour chunks and from separate light sources.
    Visible mesh ― creating lists of vertices, triangles, etc to create visible meshes.
    Collider mesh ― the same but for collider meshes.

    Average time consumed by visible mesh stage is 5ms in release .net build and only 12ms in standalone Unity build. Very disappointing.
     
    Last edited: Aug 8, 2011
  36. Kethis

    Kethis

    Joined:
    Sep 10, 2009
    Posts:
    28
    With regard to CA driven water, I found this:

    http://w-shadow.com/blog/2009/09/01/simple-fluid-simulation/

    and for the demo:

    http://w-shadow.com/water_sim/

    Also Dwarf Fortress's water does not work perfectly. It is very unrealistic.

    I do not see a reason why you should not make the amount of water bounded conserved. Ultimately more complicated behaviors such as evaporation, absorption into the soil, and rainfall (based on the amount of water lost through evaporation) could be added. I think that has the possibility to create some very interesting environments.

    I would be so happy if you could get destructive flash floods in a ravine during a rainstorm!

    This approach seems to preclude rivers, after a long enough period of time the water will balance out, but what if you created pairs of blocks, sinks and sources, and just let whatever enters the block where the sink is be pumped out of the source. This could be 'magical water teleportation' or it could require connected pipes (or pumps) to be laid. I'm liking the former.
     
    Last edited: Aug 9, 2011
  37. CaptainKiyaku

    CaptainKiyaku

    Joined:
    Feb 8, 2009
    Posts:
    324
    It's interesting to see that people still keep working on it, i love it!

    I actually want to work on this again as well, although i am still looking into a faster noise/terrain generator, that was my biggest problem.

    So i saw the code from alexzzzz and i gave it a try. It's impressive how much faster it is compared to my old one(s), but as always i have trouble to figure out how to setup the noise. For some reason i don't really understand how the noise works.

    I understand that the posted code is just an example but is this the result it should give?

    $Screen shot 2011-08-10 at 1.17.44 AM.png


    It's pretty much the example code that was posted here earlier, i use the same limitation (16 width, 128 height, 40 water level).

    I played around with the numbers, multiplied stuff, etc pp but i can't seem to get it look like a "terrain".

    Does anyone has some tips on this?

    Thanks!
     
  38. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    Kiyaku, I guess there's a problem with coordinates. I use the following convention:

    wx, wy, wz ― world coordinates of blocks
    cx, cz ― coordinates of chunks

    cx = wx / 16
    cz = wz / 16

    Generating terrain for chunks (0..1, 0..1) I get blocks (0..31, 0..127, 0..31).

    This is what I get running my sample code.
    $Captura.JPG
     
    Last edited: Aug 10, 2011
  39. CaptainKiyaku

    CaptainKiyaku

    Joined:
    Feb 8, 2009
    Posts:
    324
    Ah great that worked actually, yeah i was using 0, 16, 32, ... for chunks, forgot to divide it by the chunk size. Thanks! :)
     
  40. benac1

    benac1

    Joined:
    Aug 10, 2011
    Posts:
    9
    Hello,

    I've been lurking on this thread for quite some time now and am curious if anyone is in need of graphical help. I'm quite proficient with PS/Illustrator and am greatly interested in a voxel building game.

    -Ben
     
  41. Manmax75

    Manmax75

    Joined:
    Jun 13, 2011
    Posts:
    88
    I have had a lot of experience in the past with threading. When I get back later this week. I will post a walk-through on threading, and how to use it safely and efficiently.
     
  42. HeadClot

    HeadClot

    Joined:
    Jan 23, 2010
    Posts:
    212
    Question - is anyone planning on releasing a version of the Unity Minecraft Terrain System on the Asset Store?

    Just Curious as I Would buy it :)
     
  43. Manmax75

    Manmax75

    Joined:
    Jun 13, 2011
    Posts:
    88
    I might perhaps. I will make a fully intergratable engine with Lua Support.
     
  44. botumys

    botumys

    Joined:
    Apr 16, 2009
    Posts:
    707
    Alexzzzz, it is possible to simulate sun position and kind of shadows casting?

    And it would be great to integrate simplified thermal erosion and water cycle. Rain fall, dirt blocks becomes wet and mud. water seeps into the ground and forms groundwater areas. Water finds a way to outside, forms lacs or fall into the sea. Water evaporates from the sea...

    I know, I'm a dreamer :D
     
    Last edited: Aug 12, 2011
  45. Manmax75

    Manmax75

    Joined:
    Jun 13, 2011
    Posts:
    88
    Botumys, I have sort of erosion on my current build of sand and dirt. But its not that pretty :p With enough tweaking. It could be.
     
  46. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    The simulation, if possible, would be very expensive. There's a simple way: switch to forward rendering, create a directional light and enable shadows:

    $q.JPG

    However performance drops significantly.

    Yeah, a dreamer :)
     
  47. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    Garbage collector drives me crazy. If the player moves, collections occur every ~10 seconds and take 130..180ms, that is very annoying. Don't know how to reduce that time.
     
  48. carking1996

    carking1996

    Joined:
    Jun 15, 2010
    Posts:
    2,609
    I don't like MineCraft. That's what I think after playing minecraft...
     
  49. RingOfStorms

    RingOfStorms

    Joined:
    Oct 23, 2010
    Posts:
    584
    Aha so true, I haven't done anything in Unity for Months now =D
     
  50. RingOfStorms

    RingOfStorms

    Joined:
    Oct 23, 2010
    Posts:
    584
    Also I would like to give some information on the chunks and what not.

    I'll start with Chunks:

    Each chunk has 32768 Blocks, and goes from the sky to the bottom layer of bedrock. They are also 16x16 blocks. Here are some pics!



    Things like Grass, are actually a white texture, and use a separate image that make it look more "Real" and change colors.

    You can see that the grass changes different shades of green


    This white texture includes:
    1. Leaves
    2. Grass
    3. etc
    • Water And lava have 2 different block types for each, one that is stationary, and one that is moving.
    • Other things like Redstone torches, and repeaters, all have two block types. Off/on, or just the block and the sprite that drops to the ground.

    All I got time for atm, maybe add more later
     
    Last edited: Aug 15, 2011
Thread Status:
Not open for further replies.