Java-Gaming.org Hi !
Featured games (85)
games approved by the League of Dukes
Games in Showcase (612)
Games in Android Showcase (172)
games submitted by our members
Games in WIP (658)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
   Home   Help   Search   Login   Register   
  Show Posts
Pages: [1] 2 3 ... 102
1  Game Development / Newbie & Debugging Questions / Re: [LibGDX] Deferred Lighting on: 2015-08-31 19:15:19
First of all, you generally have both a specular intensity (how much specular light is reflected by the surface) and also a specular exponent/roughness/glossiness (how mirror-like the surface is), which affects the shape of the specular highlight. You often need to store both of them. In your case, you can store the specular exponent in the first texture's alpha component, as you only need RGB for diffuse textures.

The lighting process is pretty simple but you're mistaken on a few points. You do not want to process all lights on the screen in a single fullscreen pass. The simplest and fastest way of rendering lights is to generate light geometry. For a point light, that'd be a sphere. Spot/cone lights are a cone/pyramid thing. Directional lights (sun/moon) are indeed a fullscreen pass. The idea is to only process the pixels which are inside the light volume. In the lighting pass, you write to a single GL_RGBA16F render target with additive blending to add up all the lighting results.
2  Discussions / Business and Project Management Discussions / WSW looking for 3D modelers on: 2015-08-30 21:57:29
Hello.

We're looking for 3D modeling services for the We Shall Wake project (http://weshallwake.com). We are able to provide concept art for the work we need.



We're interested in 3 different kind of models:

 - A few hundred generic prop models. These include rocks, pipes, machines, smaller buildings, etc to populate our post-apocalyptic underground world. These props are to be very low poly, the vast majority under 300 triangles. 512x512 diffuse textures would be enough here, even less for most of the models.

 - Around 50 "tile" models, which are specific wall segments, floor segments and ceiling segments used to create randomly generated worlds. These are always under 100 triangles, often less and have strict requirements as they have to fit together seamlessly. Again, 512x512 diffuse textures would be enough here. Here are a few examples: https://docs.google.com/file/d/0B_O6GB_Ha58Mbk1DZDNKaEJSSGM/edit



We're sadly not able to pay a huge amount of money for these, as the money is coming out of our pockets.

Please contact us at theagentd<at>hotmail<dot>com if you're interested.
3  Java Game APIs & Engines / Tools Discussion / Re: jBullet3 on: 2015-08-30 03:00:50
What do you mean by "better"? OpenGL Compute != OpenCL
OpenGL compute shaders have better driver support is what he's saying.
4  Game Development / Newbie & Debugging Questions / Re: [LibGDX] Deferred Lighting on: 2015-08-29 14:56:38
It doesn't matter what kind of projection you're using. You can easily reconstruct the view space position anyway. The idea is to upload the inverse of the projection matrix to the shader, reconstruct the NDC (normalized device coordinates) of the pixel and "unproject" it using the inverse projection matrix, hence it works with any kind of projection matrix.

NDC coordinates are coordinates that go from -1 to +1 in all 3 axes. When you multiply the view space position by the projection matrix in the vertex shader when filling the G-buffer, you calculate NDC coordinates, and the GPU hardware maps XY to the viewport and Z to the depth buffer. We can undo the projection, but first we need to get all the data to do that.

First of all, you need the XY coordinates. These are easy to calculate. They basically go from (-1, -1) in the bottom left corner to (+1, +1) in the top right corner. The easiest way is to calculate them from gl_FragCoord.xy, which gives you the position (in pixels) of the pixel. Divide by the size of the screen and you have coordinates going from (0, 0) to (+1, +1). Remapping that to (-1, -1) to (+1, +1) is easy. The Z coordinate is the depth buffer value of that pixel, but the depth buffer value also goes from (0) to (+1) and needs remapping. With this, we have the NDC coordinates of the pixel. Now it's just a matter of multiplying the NDC coordinates with the projection matrix and dividing by the resulting W coordinate.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
uniform sampler2D depthBuffer;
uniform vec2 inverseScreenResolution; //Fill with (1.0 / screen_resolution) from Java.
uniform mat4 inverseProjectionMatrix;

...

vec2 texCoords = gl_FragCoord.xy * inverseScreenResolution; //Goes from 0 to 1
float depthValue = texture(depthBuffer, texCoords); //Goes from 0 to 1

vec3 ndc = vec3(texCoords, depthValue) * 2.0 - 1.0; //Remapped to -1 to +1

vec4 unprojectResult = inverseProjectionMatrix * vec4(ndc, 1.0);

vec3 viewSpacePosition = unprojectResult.xyz / unprojectResult.w;

//Use viewSpacePosition for lighting



An example G-buffer layout for deferred shading is:

COLOR_ATTACHMENT0: GL_RGBA16F: (diffuse.r, diffuse.g, diffuse.b, <unused>)
COLOR_ATTACHMENT1: GL_RGBA16F: (packedNormal.x, packedNormal.y, specularIntensity, specularExponent)
DEPTH_ATTACHMENT: GL_DEPTH_COMPONENT24: (depth)


EDIT: Actually, if you're only using an orthographic projection, you don't need the W-divide (but it doesn't harm to keep it there).
EDIT2: Also, there are lots of optimizations you can do to this. I opted to just give you the basics before diving into those. I can answer whatever questions you have about deferred shading.
5  Discussions / Miscellaneous Topics / Re: What I did today on: 2015-08-29 03:38:44
Lot's of first today for me:
- Got my first job. At a resteraunt unfortunately but I need to start somewhere
- Got my first girlfriend Cheesy
- Probably failed my first Calculus test  Emo (well I probably didn't fail but I feel like I did)

So overall my day was pretty swell  Grin
Nice.
Nice!!!
Aww...             
6  Game Development / Newbie & Debugging Questions / Re: [LibGDX] Deferred Lighting on: 2015-08-29 02:51:55
I didn't use a tutorial when I implemented it. Just reading about the concept was enough for me. What exactly are you having trouble with?
7  Game Development / Newbie & Debugging Questions / Re: [LibGDX] Deferred Lighting on: 2015-08-28 23:04:39
That article looks extremely outdated. No one has ever stored the position in a texture. You always reconstruct the view space position from the depth buffer.
8  Discussions / Miscellaneous Topics / Re: What I did today on: 2015-08-28 23:01:26
KaiHH managed to figure out how to get Nvidia Optimus laptops to use the Nvidia card. It required making a custom exe file though.
9  Discussions / Miscellaneous Topics / Re: Hello, people. on: 2015-08-27 02:25:53
1. J-draGOns sounds amazing. I should change my middle name to that.
2. Go off-topic and you the chitchat monster will get ya.
3. If I have time to drink I have time to code instead.
10  Discussions / Miscellaneous Topics / Re: What I did today on: 2015-08-26 20:03:14
Been trying out LWJGL 3. I can have one fullscreen window for each monitor and I've figured out how to do texture streaming and stuff with GLFW. Sadly, there is a load of bugs and quirks and even missing features from LWJGL 2.

11  Java Game APIs & Engines / Engines, Libraries and Tools / Re: Java OpenGL Math Library (JOML) on: 2015-08-23 22:57:21
I've found a bug. Quaternion*.set(Matrix**) does not work correctly with scaled matrices:

1  
2  
3  
4  
5  
6  
7  
      Quaternionf q = new Quaternionf();
      Matrix4f m = new Matrix4f();
      for(int i = 1; i <= 20; i++){
         float scale = i / 10f;
         q.set(m.identity().rotate(45, 0, 0, 1).scale(scale));
         System.out.println("Scale " + scale + ": " + q.x + ", " + q.y + ", " + q.z + ", " + q.w);
      }


Prints:
Quote
Scale 0.1: 0.0, 0.0, 0.13983375, 0.99017495
Scale 0.2: 0.0, 0.0, 0.23463109, 0.97208446
Scale 0.3: 0.0, 0.0, 0.30138966, 0.9535011
Scale 0.4: 0.0, 0.0, 0.350278, 0.9366458
Scale 0.5: 0.0, 0.0, 0.38733634, 0.92193854
Scale 0.6: 0.0, 0.0, 0.41625845, 0.9092463
Scale 0.7: 0.0, 0.0, 0.43938872, 0.898297
Scale 0.8: 0.0, 0.0, 0.4582705, 0.88881266
Scale 0.9: 0.0, 0.0, 0.47395375, 0.8805497
Scale 1.0: 0.0, 0.0, 0.4871745, 0.8733046
Scale 1.1: 0.0, 0.0, 0.49846226, 0.8669115
Scale 1.2: 0.0, 0.0, 0.5082066, 0.8612352
Scale 1.3: 0.0, 0.0, 0.51670027, 0.8561664
Scale 1.4: 0.0, 0.0, 0.52416706, 0.8516155
Scale 1.5: 0.0, 0.0, 0.53078103, 0.8475091
Scale 1.6: 0.0, 0.0, 0.53667897, 0.8437865
Scale 1.7: 0.0, 0.0, 0.54197043, 0.84039754
Scale 1.8: 0.0, 0.0, 0.54674363, 0.83730006
Scale 1.9: 0.0, 0.0, 0.5510708, 0.8344585
Scale 2.0: 0.0, 0.0, 0.5550113, 0.8318429
If it does not work for scaled matrices, it is pretty much a useless feature IMO. Example: I want to find the world orientation of a bone. Convert object matrix rotation to quaternion, multiply together bone rotation with model rotation. Currently this fails if the model is scaled, which it pretty much always is.

EDIT: This is the Euler angle rotations we need:
1  
quaternion.identity().rotateY(yaw).rotateX(pitch).rotateZ(roll);

This is most likely due to us using Y-up instead of Z-up.
12  Discussions / Miscellaneous Topics / Re: What I did today on: 2015-08-23 12:46:44
I implemented forking in my threading system, which I plan to use to optimize culling and other things.

My threading system is based a task hierarchy where some tasks are dependent on other tasks and can only be run after the task they depend on have finished running. If there is no dependency between two tasks, then they are allowed to run in parallel on multiple threads. In addition, each task can be split up into a number of subtasks that can execute in parallel. This is what allows the physics and graphics of WSW to be fully threaded and utilize any number of CPU cores.

Although this system is perfect when you know what work you want to do (update X physics bodies, calculate Y skeletons, etc), there are times when it is a bad fit for the problem. In the case of frustum culling objects, I use either quadtrees or octrees, and traversing an octree in one thread is pretty slow. At the same time, we have no idea how many objects we will actually find (that's why we're culling!), so how many threads we should be using depends on the data structure in question.

A good solution is to use "forking", which means that when a thread realizes it has a lot of work to do, it splits it up and hands over some of it to other threads. However, my threading system did not support that. The easiest solution would've been to create a a task with a certain number of subtasks and have them wait for the main task to generate work for them. This is inefficient though, as that locks up the threads (they're waiting for work) when they could be working on other tasks.

Instead I added support for proper forking, where a task can dynamically generate additional subtasks of itself while it's running. That means that once a subtask realizes that it has a lot of work left, it can fork itself to generate new subtasks that it can hand over part of the work to, which the worker threads will automatically pick up, execute and finish, freeing them up to work on other things again.

I wrote a small test program that tries it out. It basically has a task that forks itself 8 times, each fork sums up 5 000 000 Math.sin() calculations and then prints out the result. Here's the output of running it with a single-threaded executor:
Quote
Executing task tree.
Main task reporting. Forking 8 times.
Forking complete.
Fork 0 reporting.
1.6005898759895323
Fork 1 reporting.
1.6005898759895323
Fork 2 reporting.
1.6005898759895323
Fork 3 reporting.
1.6005898759895323
Fork 4 reporting.
1.6005898759895323
Fork 5 reporting.
1.6005898759895323
Fork 6 reporting.
1.6005898759895323
Fork 7 reporting.
1.6005898759895323
Task tree execution finished in 8.014 seconds.
Note how the main task forks itself 8 times, then after the main task is finished it picks up the forked subtasks and processes them one by one. The power here lies in the ability to dynamically generate any number of forks.

Here's the same program running with a multithreaded executor with 8 threads (I have a Hyperthreaded quad core CPU, so 8 logical cores):
Quote
Executing task tree.
Main task reporting. Forking 8 times.
Fork 0 reporting.
Fork 2 reporting.
Fork 1 reporting.
Fork 6 reporting.
Forking complete.
Fork 5 reporting.
Fork 4 reporting.
Fork 3 reporting.
Fork 7 reporting.
1.6005898759895323
1.6005898759895323
1.6005898759895323
1.6005898759895323
1.6005898759895323
1.6005898759895323
1.6005898759895323
1.6005898759895323
Task tree execution finished in 1.565 seconds.
There are some interesting points here. Note that the forks start running as soon as they're created, and 4 forks even started executing before all forks have been issued. The forks then all execute in parallel on multiple threads, in contrast to the serial execution of the single threaded executor. Since they're calculated in parallel using multiple cores, the task tree finishes execution in 1/5th as long time.

I plan to use this for frustum culling. Currently the frustum culling is threaded per "view", which means that each camera and shadow map is calculated in parallel, but this is a very uneven workload. The camera is usually much much more expensive to cull for leading to one subtask taking much longer time to finish than the others. With this forking system, big views can be split up into multiple smaller jobs while small views that are cheap to cull can avoid the overhead of forking and synchronization.



I once has this grid that was self-adjusting. Every N frames it would either grow or shrink in cell size, and measure performance differences. It would converge to the optimal solution, and then adjust itself when the environment changed, and converge to the new optimal solution. Give it a try, it is easy to implement.
Probably too much work. We'll just tweak it to a good value. Really interesting idea though.
13  Java Game APIs & Engines / Engines, Libraries and Tools / Re: Java OpenGL Math Library (JOML) on: 2015-08-22 22:55:16
We're having problems with Euler angles in WSW. It seems like the order we're supposed to use depends on if you use a Y-up or Z-up coordinate system. We're investigating how to solve it (it was basically hacked before), but if possible it'd be great if you could implement all 6 orders (XYZ, XZY, etc) so we can try them out. I realize that that might be a bit tedious, but I think it will be useful for people with odd coordinate systems. If you think it's a bad idea, I can give you our specific requirements when we figure them out.
14  Game Development / Newbie & Debugging Questions / Re: LWJGL GL_INVALID_ENUM reason on: 2015-08-22 19:04:49
JVM crash means you're telling the driver to read from somewhere it's not allowed to. Check your VBOs and IBOs, make sure everything is bound and you're not making it read out of bounds.
15  Game Development / Game Mechanics / Re: Case Studies on: 2015-08-22 18:58:37
Short answer atan & atan2 are (vs. acos and asin):
1) faster to compute
2) don't have input domain issues
3) are more robust.

I can give some details if you want.
Hmm, interesting. 2 and 3 I can understand, but why is it faster to compute?
16  Game Development / Game Mechanics / Re: Case Studies on: 2015-08-22 17:38:18
I had in mind geometric reasoning...but this is all headed in the right direction.  Gosh we have |a||b|cos(t), if we could cheaply find |a||b|sin(t) we could use atan2.
Why is atan2() so much better than acos()?
17  Discussions / Miscellaneous Topics / Re: What I did today on: 2015-08-22 14:43:44
Pretty much finished converting WSW to using JOML instead of LibGDX. Excellent library. Faster implementations, thread-safety out-of-the-box, smaller. Still awaiting a few features to be able to finish it and see how broken it is. =P

Did some profiling now that skeleton animation is over twice as fast thanks to JOML and found a physics bottleneck. The physics simulation uses a 2D grid to quickly find nearby bodies for collision detection. Each "tile" in the grid is just a list of bodies that are in that grid. To query nearby bodies, you pass in a position and a radius, and the grid returns all bodies that intersect the square the position+radius forms (circle test is too expensive). Since the grid tile size is bigger than the bodies, each body generally only needs to check 1 tile, or 2 or 4 if the query area extends across a grid boundary. While doing some optimizations getting rid of some unnecessary divides, I realized that there was a bug in there that expanded the search area by 1 tile in each dimension, meaning a 1x1 check turned into a 2x2, and a 1x2 check turned into a 2x3. This had a huge impact on performance as it basically does 2-4x as much work. In combination with getting rid of a few divides, Math.floors() and Math.ceils(), I almost managed to double the body-body collision testing performance.
18  Java Game APIs & Engines / Engines, Libraries and Tools / Re: Java OpenGL Math Library (JOML) on: 2015-08-22 13:12:15
Inject a proxy method, then refactor.
It's not that simple as I'm selectively converting part of it to use doubles.
19  Java Game APIs & Engines / Engines, Libraries and Tools / Re: Java OpenGL Math Library (JOML) on: 2015-08-22 11:38:52
Thanks, you understood everything correctly.  Wink

Quote
Also badly missing the ability to initialize matrices and quaternions from Euler angles.
There is
Quaternion.setEulerAnglesXYZ/setEulerAnglesZYX
, depending on your wanted rotation order.
If you desperately need also that function in Matrix, then that could be added. Otherwise, you could initialize a quaternion with that and then set a matrix to that quaternion.
It'd be really nice to have in Matrix** as well.

I've just manually "fixed" ~3000 errors over 2 days in WSW as a result of the switch. I literally dreamt about code last night.
20  Java Game APIs & Engines / Engines, Libraries and Tools / Re: Java OpenGL Math Library (JOML) on: 2015-08-22 10:33:30
Also badly missing the ability to initialize matrices and quaternions from Euler angles.
21  Java Game APIs & Engines / Engines, Libraries and Tools / Re: Java OpenGL Math Library (JOML) on: 2015-08-22 09:54:58
 - There's no AxisAngle4d class it seems, and the Quaterniond constructor does not accept AxisAngle4fs. Currently need to do new Quaterniond().set(AxisAngle4f).

 - Matrix4d.translationRotateScale(Vector3d, Quaterniond, Vector3d) is missing, only the version with float Vectors exists (raw double argument version exists).



A problem I'm continuously getting is converting between float and double versions of objects.

Examples:
 - Getting the world position of bones. Object matrix is a Matrix4d, calculated local bone position is Vector3f. This works reasonably well as Matrix4d can take in a Vector3f.
 - Particles use float precision, but I have most matrices as double matrices. Matrix4f.set(Matrix4d) does not exist, which would be useful.

In my opinion, the float versions should at the minimum have setters for reading from the double versions (Vector3f.set(Vector3d), etc), but actually having all functions being able to take in double arguments (like how the double versions have functions that take in the float versions) would be really useful.

Also, Quaterniond seems to miss float versions of its functions.
22  Game Development / Game Mechanics / Re: Case Studies on: 2015-08-22 08:47:39
I couldn't find a version for Math.sin on google which is a pity.
Sin can be calculated either using the cross product between two vectors if you need the sign as well, or if you don't need the sign by simply using the fact that (cos^2 + sin^2 = 1), which translates to
double sin = Math.sqrt(1 - cos*cos);
, but this is less useful.

The cos = dot-product can be used for lots of useful things. A common appliance is field-of-view testing for AI. Given an NPC that is facing a certain angle, you can precompute its normalized view vector each frame. If his field-of-view is 30 60 degrees, you can calculate cos(30). To check if someone is in the NPC's field-of-view:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
//Precomputed:
Vector3 normalizedViewVector = ...;
float cosCutoff = (float)Math.cos(30);

//For each enemy:
Vector3 vectorToEnemy = target.position - me.position;
boolean canSee = dot(me.normalizedViewVector, vectorToEnemy) / vectorToEnemy.length() > cosCutoff;
if(canSee){
    ...
}


This has extremely good performance as it only uses conventional math plus a single square root to calculate length(). The precomputation is generally cheap as it only needs to be done N times per frame, while the enemy testing may be done up to N^2 times.

EDIT:
The dot-product calculates the cosine of the angle from the view vector, so for a 90 degree field of view, you calculate cos(45). This even works for values over 90 degrees, i.e to give the NPC a blind spot directly behind it.
23  Java Game APIs & Engines / Engines, Libraries and Tools / Re: Java OpenGL Math Library (JOML) on: 2015-08-21 20:55:56
Matrix4d.set(Quaternion*) is missing. >_<
24  Game Development / Game Mechanics / Re: Case Studies on: 2015-08-21 20:55:31
You forgot your point.
25  Java Game APIs & Engines / Engines, Libraries and Tools / Re: Java OpenGL Math Library (JOML) on: 2015-08-21 15:02:53
Thanks, works great!
26  Java Game APIs & Engines / Engines, Libraries and Tools / Re: Java OpenGL Math Library (JOML) on: 2015-08-21 11:27:53
I am using mapped VBOs, so generating a new FloatBuffer each time I map it is something I would like to avoid. In addition, I'm storing non-float stuff in it as well, so keeping it as ByteBuffer is optimal for me.

Edit:
Matrix4.get(Quaternion) should be renamed to Matrix4.getRotation(Quaternion), to complement getTranslation() and getScale().
27  Java Game APIs & Engines / Engines, Libraries and Tools / Re: Java OpenGL Math Library (JOML) on: 2015-08-21 09:03:39
G'morning. I just pulled the latest changes. getScale() works well, but removing Vector3*.mul(Matrix4*) broke a lot of my code. It'd be nice if we had mulPoint() and mulDirection() in Vector3* as well. I still need the <store double matrix at float precision in byte buffer> function. >_<

In other news, we're starting the switch to JOML for WSW today.
28  Java Game APIs & Engines / Engines, Libraries and Tools / Re: Java OpenGL Math Library (JOML) on: 2015-08-20 22:37:03
I still vote for renaming it to store/load. I don't think the get-set logic applies in this case since the JOML classes aren't buffers. Getting in NIO implies reading data from a buffer, but getting in JOML implies writing to a buffer. Load/store makes sense as it mimics the old OpenGL functions as well, where glLoadMatrix(FloatBuffer) loads a matrix from a given buffer. The fact that the set() functions are filled with buffer.gets() is a bad sign IMO. >___>
29  Java Game APIs & Engines / Engines, Libraries and Tools / Re: Java OpenGL Math Library (JOML) on: 2015-08-20 21:53:56
Finally home and ready to try out JOML stuff in WSW. Still missing three functions:



Matrix**.getScale(Vector**): gets the scaling of each axis. Used to calculate LOD level based on scale of model from a model's matrix.

Vector3*.mulRotate(Matrix4*): multiplies the vector by the matrix with w=0, i.e. multiply by matrix but ignore translation. I use this to rotate directional and cone light direction vectors by the view matrix's rotation.

Matrix4d.getFloat(int index, ByteBuffer buffer): stores the double matrix in a ByteBuffer as floats. Currently limited to doubles only for ByteBuffers. I use this to store model matrices in a mapped VBO (a ByteBuffer).



I really think that the "get" functions should be renamed to "store". The name really makes no sense right now. LWJGL's math library called it store(), since you store the matrix in the buffer. The "set" functions make more sense as you set the value of the matrix to that of the data in the buffer/array. LWJGL called this operation "load" which I prefer, but "set" is okay IMO.


EDIT: Minor note: the Vector**.distance() and distanceSquared() functions recalculate (x - this.x) etc twice (although the compiler probably caches that for you). Might want to compute those to local variables just to be sure. It makes the code more readable as well.
30  Game Development / Game Play & Game Design / Re: Article on pay to win games in Japan on: 2015-08-19 22:48:29
Choosing stupid* people as your target demographic is never a bad business decision. As true in mobile games as in door to door sales.
Username checks out.
Pages: [1] 2 3 ... 102
 
afikri (8 views)
2015-08-31 09:30:22

afikri (17 views)
2015-08-31 09:30:07

afikri (7 views)
2015-08-31 09:27:24

afikri (11 views)
2015-08-31 09:26:40

Roquen (16 views)
2015-08-29 11:30:54

GamerC4 (28 views)
2015-08-22 20:38:50

GamerC4 (24 views)
2015-08-22 20:37:18

GamerC4 (28 views)
2015-08-22 20:37:01

Kefwar (33 views)
2015-08-22 18:07:24

GamerC4 (26 views)
2015-08-22 01:00:24
HotSpot Options
by Roquen
2015-08-29 11:33:11

Rendering resources
by Roquen
2015-08-17 12:42:29

Rendering resources
by Roquen
2015-08-17 09:36:56

Rendering resources
by Roquen
2015-08-13 07:40:51

Networking Resources
by Roquen
2015-08-13 07:40:43

List of Learning Resources
by gouessej
2015-07-09 11:29:36

How Do I Expand My Game?
by bashfrog
2015-06-14 11:34:43

List of Learning Resources
by PocketCrafter7
2015-05-31 05:37:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!