Java-Gaming.org Hi !
Featured games (90)
games approved by the League of Dukes
Games in Showcase (731)
Games in Android Showcase (217)
games submitted by our members
Games in WIP (798)
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 4
1  Discussions / Miscellaneous Topics / Re: Annoying Interview Q on: 2017-04-26 09:15:03

Small companies/startups is the best way to gain new knowledge and skills. I'd hate to be stuck in a large company in some little corner doing the same crap over and over again, regardless of how good the pay is. The Destination is nowhere near as awesome/fun as the journey to get there.

Working remote has its own challenges especially from a management point of view and also communication. I personally prefer working in person with the rest of the team. More fun that way aswell.
2  Discussions / Miscellaneous Topics / Re: Annoying Interview Q on: 2017-04-24 23:42:50
We changed our strategy at our workplace for hiring developers. We don't even ask them where they graduated, or what they can/can't do. We give them a real-life, very relevant problem that currently exists in our stack, and get them to come up with a solution. Of course we pay them a temporary contract rate for the project and they can also work from home. The expected time it takes is generally 2-3 days (if one of us had to sit down and do it) so we expect candidates not to take more than 2 weeks.

Of potentially 20-30 candidates, only 1-3 actually finish it. The final interview is simply a discussion about the problem and their solution (and why they did certain things the way they did, the thought process etc...). By the time they are hired, they have already contributed relevant code into the stack.
3  Discussions / Miscellaneous Topics / Re: Annoying Interview Q on: 2017-04-24 13:33:16
requires a computer and sometimes an internet connection. Almost always requires a monkey to maintain it.
4  Game Development / Newbie & Debugging Questions / Re: OpenGL ES glReadPixels() blocking on PBO on Android on: 2017-03-27 05:28:43
Unfortunately the glGetTexImage/glGetTextureImage is not available in the OpenGL ES spec for Android. Not even via JNI.

And from https://www.khronos.org/opengl/wiki/Pixel_Buffer_Object#Downloads in the Downloads section states this...

Quote
This is really where PBOs shine, performance-wise. The savings when using PBOs for downloads are substantial. Again, as long as you have something to do during that time.

That's great and all, except the transfer is actually blocking on my code, making the whole thing obselete. I might aswell just glReadPixels() on the FBO directly.
5  Discussions / General Discussions / Re: C++/Java Engine without GC in graphics on: 2017-03-25 20:59:26
Use a language you are comfortable with. You won't gain any immediate advantage just because you use C/C++. There will be some hurdles and problems that you will need to solve.
6  Game Development / Newbie & Debugging Questions / Re: Check which thread is calling a static method on: 2017-03-24 04:14:18
This seems to have what you're looking for.

http://stackoverflow.com/questions/4684274/how-do-you-check-which-thread-is-executing-code-in-java
7  Game Development / Newbie & Debugging Questions / Re: OpenGL ES glReadPixels() blocking on PBO on Android on: 2017-03-24 02:24:47
Thank you for the reply basil_

I was hoping someone would reply  Grin

What I'm confused about is that glReadPixels from FBO -> PBO is meant to be an async call, but in all of these cases it actually blocks the render thread for a long time.
From my source i'm actually using double FBO's and each FBO has double PBO's, but this makes zero difference since glReadPixels still blocks.

And it's interesting about other threads, I wasn't aware that GL calls could be made in a non-GL thread on Android. I'll give that a shot.
8  Game Development / Newbie & Debugging Questions / OpenGL ES glReadPixels() blocking on PBO on Android on: 2017-03-20 23:33:54
Greetings JGO Community,

I'm stuck on a particular problem regarding glReadPixels and OpenGL ES.

I'm having an unusual problem while working on an openGL project. Essentially I require frame data in GRAYSCALE single channel format for some CV stuff. I'm using a custom shader, an FBO and PBO's to get the task done. The data I'm rendering is the camera view from Android.

The flow of the program is as follows.
  • bind the generated FBO
  • draw() to the FBO
  • bind PBO and glReadPixels()
  • bind PBO from previous frame and glMapBufferRange()
  • process the provided pixel data from glMapBufferRange()

I'd like to actually confirm that the process is working fine. What i'd like to know is whether there is anything that can be done to increase the performance. I'm going to post some of the code I'm using so we can all follow.

The PBO generator code

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
public void setupPBO() {
        final int[] pbuffers = new int[2];

        GLES30.glGenBuffers(2, pbuffers, 0);

        for (int i = 0; i < pbuffers.length; i++) {
            GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, pbuffers[i]);
            GLES30.glBufferData(GLES30.GL_PIXEL_PACK_BUFFER, width * height, null, GLES30.GL_DYNAMIC_READ);
            GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, 0);
        }

        pbo_id[PBO_PRIMARY_ID] = pbuffers[0];
        pbo_id[PBO_SECONDARY_ID] = pbuffers[1];
}


The PBO Bind/Read Code. Before this call is made, I bind the FBO which was rendered into from the previous frame.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
public void bindReadSwapPBO() {
        GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, pbo_id[currentBuffer]);
        GLES30.glReadBuffer(GLES30.GL_COLOR_ATTACHMENT0);

        // glReadPixels is done from the JNI layer. Only read single channel GL_RED
        // This blocks for up to 50ms. Should be an Async call?
        JNI.glReadPixels(0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, 0);

        GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, 0);

        final int prevBuffer = previousBuffer;

        previousBuffer = currentBuffer;
        currentBuffer = prevBuffer;
}


This code is what handles grabbing the data from the PBO. Can confirm that this works properly and the call is virtually 0ms.

1  
2  
3  
4  
5  
6  
7  
8  
9  
public void bindMapPBO() {
        GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, pbo_id[currentBuffer]);

        // read our data from the PBO.
        JNI.glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, width * height, GL_MAP_READ_BIT);

        GLES30.glUnmapBuffer(GLES30.GL_PIXEL_PACK_BUFFER);
        GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, 0);
}


And this is where the performance problem is coming from. Currently I'm reading back pixels which are 480 x 360 single channel grayscale (calculated from a shader). I've ran some benchmarks and results are below.

  • 40-50ms -> JNI.glReadPixels(0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, 0);
  • 0-1ms -> JNI.glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, width * height, GL_MAP_READ_BIT);

From what I understood is that glReadPixels from the PBO is not meant to be a blocking call, but for whatever reason it's blocking it here (and performing far worse than just reading from an FBO). It seems glMapBufferRange is behaving as expected, and returning the required data properly.

The only thing i can think of is that I'm using GL_RED and only reading back a single channel, but this still doesn't explain why glReadPixels is blocking.

Devices I've used for bench-marking (consistent behaviour).

  • HTC One M8s (40-50ms)
  • Nexus 5x (20-30ms)
  • Google Pixel (15-30ms)

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
public void setupFBO() {
        final int[] values = new int[1];
        GLES30.glGenTextures(1, values, 0);
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, values[0]);

        // we only want GRAYSCALE / Single channel texture
        GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_R8, texWidth, texHeight, 0, GLES30.GL_RED, GLES30.GL_UNSIGNED_BYTE, null);
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_NEAREST);

        this.tex_id[0] = values[0];

        GLES30.glGenFramebuffers(1, values, 0);
        GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, values[0]);

        this.fbo_id[0] = values[0];
        GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, this.tex_id[0], 0);

        final int status = GLES30.glCheckFramebufferStatus(GLES30.GL_FRAMEBUFFER);

        if (status != GLES30.GL_FRAMEBUFFER_COMPLETE) {
            Debug.LogError("Framebuffer incomplete. Status: " + status);
        }

        GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);
}


The full render code. I've deconstructed as much of the logic and flow as possible for clarity.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
        // bind the offscreen FBO and render the current camera frame
        GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, dualFBO.getID());
        camera.draw(ShaderType.GRAYSCALE);

        // ping-pong the FBO ID's
        dualFBO.swap();

        // dualFBO will now return the ID for last frame
        GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, dualFBO.getID());

        // bind the current PB and submit (meant to be async) glReadPixels
        GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, dualPBO.getID());
        GLES30.glReadBuffer(GLES30.GL_COLOR_ATTACHMENT0);

        // this call locks for 30-50ms... why? (meant to be async???)
        JNI.glReadPixels(0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, 0);

        GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, 0);

        // ping-pong the PBO ID's.
        dualPBO.swap();

        GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, dualPBO.getID());

        // this call is instant
        JNI.glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, width * height, GL_MAP_READ_BIT);
   
        GLES30.glUnmapBuffer(GLES30.GL_PIXEL_PACK_BUFFER);
        GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, 0);

        // the CV stuff, which now has data from the glMapBufferRange
        JNI.processCV();


Any help in this matter would be highly appreciated! I've never had to read data back from openGL every frame in real-time, so I'm at wits end here. Below is some more code so you guys can get an idea on how the logic flows.
9  Discussions / Miscellaneous Topics / Re: What I did today on: 2016-05-28 02:35:21
I'm officially a high school senior now. Can't wait to get out of here!

Stay in school, for as long as you can.
10  Game Development / Shared Code / Re: Bits, Bytes and Insanity on: 2016-05-28 00:11:35
I've used this to great effect in generating image masks to be transferred over a network. Use this and a simple quad-tree encoding gives a best case scenario (for a mask) of 22 bits. 10 bit for width, 10 bits for height and 2 bits for the data (1 bit for quadtree node and 1 bit for the mask state). Best case for masks with either all 0's or all 1's for the mask.

Worst case would be something like a checker pattern down to each pixel, where the overall size would be worse than using a bit array mask, mainly due to the extra bit's required for the quad-tree subdivision.

Obviously best cases are rare, still good to think about it!
11  Game Development / Shared Code / Bits, Bytes and Insanity on: 2016-05-27 13:13:18
Greetings JGO!

I've come here to share some code which I've been using to feed my own personal arrogance and the need for exploration (in code of course).

So what is this code?

It's essentially a naive compact storage method which I've used in my own experiments. It's not really optimized but I've used it and continue to use it. It's become something of a small passion of mine. It did take some thought and time to put together properly.

Let's look at an example where something like this might come in handy.

Let's say you need to store a bunch of values into a file. These values range between 0 and 120. For this example it's simple, you can instantiate an array of bytes (8 bits) with each position in the array capable of holding all your values as long as they are between the original design of 0 and 120.

But what if?

Lets say you need to store a bunch of values into a file. These values range between 0 and 555. For this example it's also simple, you can instantiate an array of shorts (16 bits) with each position in the array capable of holding all your values as long as they are between the original design of 0 and 120.

In general, this will be of no problem, but there are scenarios where you may wish to squeeze every little saving in file size as you can, especially for cases where it will be transferred over a network.

The Binary Compactor was created to solve this problem. It essentially allows you to write and read values with variable bit lengths. In the case of the 2nd example, you can fit values of 0-555 into 10 bits, which will save you 6 bits of information per array position.

Let's look at some code on how this works.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
// first, we initialize a new writer with default write position at 0
// can also be used to load a previous stream from file
BitWriter writer = new BitWriter();

// let's write 3 boolean values, these will take a total storage of 3 bits
writer.write(true);
writer.write(false);
writer.write(true);

// let's write some integers. First argument is the value to be written,
// 2nd argument is the number of bits it will take.
writer.write(555, 10);
writer.write(62, 6);
writer.write(1792, 12);
writer.write(57892, 17);
writer.write(7658, 14);

// and just for fun, dump this stream into console
System.out.println("BITS: " + writer.getBitString());

// prints
// BITS: 10111010 10001011 11100000 00011100 01001000 10001110 01010111 10111000


Now to iterate those values back.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
// define a new iterator from the writer
BitIterator it = writer.getIterator();

// start iterating the previous variables. Notice how you have to tell
// the iterator how many bits to read

// the boolean values from before
System.out.println(it.getNext32(1));
System.out.println(it.getNext32(1));
System.out.println(it.getNext32(1));

// the integer values from before
System.out.println(it.getNext32(10));
System.out.println(it.getNext32(6));
System.out.println(it.getNext32(12));
System.out.println(it.getNext32(17));
System.out.println(it.getNext32(14));

// prints
// 1
// 0
// 1
// 555
// 62
// 1792
// 57892
// 7658


Unfortunately the entire method is too large to post in here however it is available free of charge (along with a C# implementation) at my github repository https://github.com/DavidArayan/EzyBits

Will most of you have any use for this? NO
Should you use this instead of normal int/short/longs? NO

However there will come a time, at some place, somewhere in your own experiments where you would say "I wish I had an easy method of reading and writing any variable in any bit length I want, cause of reasons".

Contributions, Feature Requests and Comments all welcome!
12  Discussions / General Discussions / Re: Unity3D/2D on: 2016-02-23 07:40:10
I'm in a love/hate relationship at the moment with C#

I've started to get used to the get; set; operators and use it more frequently in my code style.
I also love how you can overload the [] and other operators.

But honestly.. that's about it.

In all my years of programming, I've come to witness some the worst written code in C#. Thankfully all of it is from outside our company so its often a one-time affair. Still gives me nightmares.
Despite being in C# land for the past few years, I still find myself doing rapid prototyping/projects in Java.
13  Discussions / General Discussions / Re: Unity3D/2D on: 2016-02-21 22:02:18
Some games made with Unity

Hearthstone
RUST
Cities: Skylines
Kerbal Space Program
Homeworld Deserts of Kharak
Eve: Valkyrie

I've played all but the last two. Cities: Skylines performs better than EA's newest Sim City (which ran like a dog and played like a dog).

Any game will suck and run like a dog if the developer doesn't spend the time and resources optimizing the code, regardless what technology is used.
14  Discussions / General Discussions / Re: Unity3D/2D on: 2016-02-21 01:21:47
I've been working with Unity3D for the last 3 years or so.

Coming from a Java background and had written my own engine in it, I would agree that some of the things Unity3D does is less than optimal, however this is a problem that plagues most Game Engines anyway.

In the end though, none of it matters. What matters is to get a project out the door in a good time, afterwards you can invest time and energy optimizing the project to run silky smooth. This is something that you will have to do with most projects anyway, regardless which language/library you used to write them.

One thing that is excellent wit Unity is how easy it is to extend it for your own needs. I've got no less than 12 different libraries I've written to help me with the various projects that I'm working on ranging from one-click UI template creators to mesh optimization tools to automated testing of code. You'll find that again, this is something you'll have to do regardless which engine/framework/library you use. One of the more recent fun extensions was a tool which allows me to import LibGDX's G3DJ and G3DB file formats which are downloaded and displayed at runtime.

Less bashing, more writing!

15  Discussions / General Discussions / Re: Achievement Milestones on: 2015-05-17 14:42:17
1  
2  
3  
4  
5  
6  
7  
8  
while (true) {
     if (myCurrentProject.IsDone()) {
          myCurrentProject = Brain.Instance().GetNewProject();
          myCurrentProject.Start();
     }
}

GetNewHobbyOrDie();
16  Discussions / General Discussions / Re: What's your day job? on: 2015-02-26 00:52:05
Freelance developer/research for a company doing Augmented Reality and Virtual Reality.

DrHalfway: That sounds crazy. I'm currently in a class involving AR and VR. I just started a project using OpenCV, and my mind is blown with every line of code I write. Can you tell us more about some of the projects you work on?

Can't say much other than we are building a platform to perform Augmented Reality and Virtual Reality from the "Cloud" (hate that word!). If I had it my way, i'd be doing it completely differently.

All things aside, we have done some nice things with SLAM. From what I've seen, the new MS Hololens does seem to use similar technology for its AR.

Quite the exiting time to be in this part of the industry. Unfortunately can't say anymore due to NDA's =[
17  Discussions / General Discussions / Re: What's your day job? on: 2015-02-16 11:11:16
Freelance developer/research for a company doing Augmented Reality and Virtual Reality.

They had crazy and insane ideas.

I made them into a reality for small pocket change.

I regret nothing.
18  Discussions / General Discussions / Re: Future career in programming and school suggestions? on: 2015-02-16 11:08:58
I've always been more curious rather than ambitious. School never rewards Curiosity or Individualism. I hated school, used to suck at school and just barely made it out.

Almost 6 years later now, I've got my Graduate Degree in Games Programming, I'm doing Masters by Research and have 3 papers due to be published and in 3 years time I'll have my Ph.D (finally getting the damn title).

My curiosity has led me to find freelance work for a great company doing research and development in Augmented Reality and Virtual Reality. I was given a chance, I worked hard and took my place.

6 years is not a long time. I'm curious where I will be in 6 years time!

Follow your heart, follow your dreams and trust in your gut feeling. Your life is your own, you never know where your path will lead you. Work hard doing what you love and think is right. Hours will turn into days, into weeks, months and years and you will be rewarded along the way.

Wish you the best of luck!
19  Discussions / Miscellaneous Topics / Re: Is drinking half a bottle of vodka safe? on: 2014-10-10 02:21:24
I am a heavy Vodka drinker.

Take these things into consideration.

1) Vodka has a delayed timer, meaning you don't feel the effects until a bit after (5-10 minutes)
2) If you're anything like my Japanese friend, the above rule does not apply. The timer is about 2 seconds before you go red cheeked, and another 2 seconds before you plummet into a deep and undisturbed sleep.
3) Contrary to popular belief, good vodka is good for you in moderation.
4) There is good vodka and there is bad vodka. If you are outside of Russia and some other European countries, chances are you're drinking the bad vodka. Go to your local vodka house and get some good vodka.
5) If you're in this forum, I assume you have "some" willpower, even when drunk. Always be aware of yourself and you'll avoid doing stupid shit.
6) There are happy drunks and then there are depressed drunks. You won't know which one you are until you try. I'm a happy drunk. On the other spectrum, there are dangerous drunks. If you are a dangerous drunk, I automatically assume you're a spineless coward and a bitch with zero willpower. Excuse my french.

Here is a simple algorithm to help you out.

1  
2  
3  
4  
while(selfAware(this)) {
      drinkVodkaShot(1);
      yield return waitForMinutes(5.0f);
}


Alternative Algorithm for real men.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
while(true) {
      sayToast("Insert Interesting Toast Message Here");
      drinkVodkaShot(1);
      yield return waitForMinutes(5.0f);

      if (timeToGoHome()) {
            sayToast("Insert Interesting Toast Message Here");
            drinkVodkaShot(1);
   
            break;
      }
}
20  Game Development / Performance Tuning / Re: Taming Java GC to prevent stutter, an in-depth post on memory management on: 2014-04-24 10:28:48
Some of those complex collision detection functions can be a nightmare on the GC to the point where I modified some of them to use local floating point x,y,z values and static reusable Vector3 objects and manual math where applicable. A complete nightmare to write and even a bigger nightmare to maintain, it makes for some of the ugliest code, however, for sake of performance... I'm even looking for openCL alternatives for some of those functions.
21  Discussions / General Discussions / Re: 30 vs 60 vs 120 FPS on: 2014-03-20 02:45:37
I can notice the difference between 60 and 120 but only during competitive gameplay and only if the monitor is running at 120Hz.
22  Discussions / General Discussions / Re: Programmer jokes on: 2014-03-20 02:39:07
99 little bugs in the code
99 bugs in the code
Fix one bug, compile it again
101 little bugs in the code.

101 little bugs in the code
101 bugs in the code
Fix one bug, compile it again,
103 little bugs in the code.
23  Game Development / Newbie & Debugging Questions / Re: From immediate mode to VBO mode LWJGL (basic) on: 2013-10-15 05:49:49
perhaps this post will help.

http://www.java-gaming.org/topics/simple-vertex-array-immediate-drawer/30852/view.html

take same concept and apply VBO instead of VA
24  Discussions / General Discussions / Re: Off-Topic: Java and Framework Alternatives - 'Friendly' Discussion. on: 2013-09-29 14:05:38
I've recently used Unity 3D and must say, for an engine so hyped its missing quite a few critical features required to make great games, I've found it average at best.

I much rather the flexibility of writing an engine from scratch, at least I know what I'm getting for my time investment.

Currently looking at implementing sparse voxel octrees as a java framework, which is fun, interesting and pretty darn exciting!
25  Game Development / Performance Tuning / Re: Concurency in 3d engine. on: 2013-09-29 11:37:04
I used a similar strategy in one of my experiments. For every loop, there will be a thread for the render and a thread for the logic, both running concurrently. Once logic is complete, you buffer all the needed data as "read only" which the render thread will then access, this way the logic thread will move onto the next loop while the render thread grabs the current frame data and renders it. If incase one is running ahead of time, ie, a render thread is still rendering previous frame data as this frame is complete, the logic thread will stall and wait for the render thread to complete. Using this method means that a total time taken for a single frame is the same time as the thread which takes longer to compute.
26  Discussions / General Discussions / Re: What You Do When You are Burnt Out on: 2013-09-15 14:39:50
When I'm burnt out, I go play a good game of dota with mates. If I'm burnt out of dota, I just write programming tutorials.
27  Game Development / Newbie & Debugging Questions / Re: Vectors! on: 2013-09-03 05:50:31
Velocity is a vector which has both "direction" and "speed"

You find the direction by normalizing the Velocity vector, and the speed is the magnitude or the length of the vector.

If you have a 2D sprite at position V1 = <x1, y1> and want to move it a 2D position with vector V2 = <x2, y2> you can find the velocity vector for movement by doing the following

velocity = V2 - V1

float speed = velocity.magnitude
Vector direction = velocity.normalize

I hope that explains things a bit =]
28  Discussions / Miscellaneous Topics / Re: Blogs? on: 2013-08-14 09:08:42
My Devblog in my Signature  Cool
29  Game Development / Articles & tutorials / Triangle Intersection Tests on: 2013-08-08 11:47:14
Hello JGO Community. No I'm not dead, just taking a small Hiatus from Java Game Development!

I come today to share some source code I've been working on for various methods using the Unity framework. Originally I wrote the methods in C#, however for the sake of this tutorial I've converted them in Java just for you! (well not really, I just like Java)

This tutorial is a direct follow up from my previous tutorial for basic collision detection found in the following link http://www.java-gaming.org/topics/basic-collision-detection/27326/view.html.

The methods presented in this tutorial are for processing and intersecting 3D triangles, you will find this useful when creating things such as advanced decal frameworks or object slicers which could work for both 2D and 3D.

For sake of this tutorial, I assume that you have a working Vector2 and Vector3 library. If you don't, libraries such as LibGDX or LWJGL provide one for you. Depending on how you layout your code, you may need to perform some light modifications, otherwise it should work by simply copy pasting the code into your Java projects.

The method presented below is for finding the closest point between a triangle and a point. Very useful method in certain situations.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
// for triangle a-b-c return a point q in triangle that is closest to p
public static Vector3 closestPtPointTriangle(Vector3 p, Vector3 a, Vector3 b, Vector3 c) {
   // Optimized version as found in book Real time collision detection
   // b - a
   Vector3 ab = Vector3.subtract(b, a);
   
   // c - a
   Vector3 ac = Vector3.subtract(c, a);
   
   // p - a
   Vector3 ap = Vector3.subtract(p, a);
   
   float d1 = Vector3.Dot(ab, ap);
   float d2 = Vector3.Dot(ac, ap);
   
   if (d1 <= 0.0f && d2 <= 0.0f) {
      return a;  
   }
   
   // p - b
   Vector3 bp = Vector3.subtract(p, b);
   
   float d3 = Vector3.Dot(ab, bp);
   float d4 = Vector3.Dot(ac, bp);
   
   if (d3 >= 0.0f && d4 <= d3) {
      return b;  
   }
   
   float vc = d1 * d4 - d3 * d2;
   
   if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) {
      float v = d1 / (d1 - d3);
     
      // a + (ab * v)
      return Vector3.add(a, Vector3.multiply(ab, v));
   }
   
   // p - c
   Vector3 cp = Vector3.subtract(p, c);
   
   float d5 = Vector3.Dot(ab, cp);
   float d6 = Vector3.Dot(ac, cp);
   
   if (d6 >= 0.0f && d5 <= d6) {
      return c;  
   }
   
   float vb = d5 * d2 - d1 * d6;
   
   if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) {
      float w = d2 / (d2 - d6);
     
      // a + (ac * w)
      return Vector3.add(a, Vector3.multiply(ac, w));
   }
   
   float va = d3 * d6 - d5 * d4;
   
   if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) {
      float w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
     
      // b + w * (c - b)
      return Vector3.add(b, Vector3.multiply(Vector3.subtract(c, b), w));
   }
   
   float denom = 1.0f / (va + vb + vc);
   float vn = vb * denom;
   float wn = vc * denom;
   
   // a + ab * vn + ac * wn
   // this can be done with one line
   
   Vector3 abvn = Vector3.multiply(ab, vn);
   Vector3 acwn = Vector3.multiply(ac, wn);
   
   // return result
   return Vector3.add(a, Vector3.add(abvn, acwn));
}


Below is a quick method to check if a point p is in a triangle defined by points a-b-c

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
// check if point p is in triangle a-b-c
public static boolean pointInTriangle(Vector3 p, Vector3 a, Vector3 b, Vector3 c) {
   // bring triangle to p coordinate frame
   Vector3 pa = Vector3.subtract(a, p);
   Vector3 pb = Vector3.subtract(b, p);
   Vector3 pc = Vector3.subtract(c, p);
   
   float ab = Vector3.Dot(pa,pb);
   float ac = Vector3.Dot(pa,pc);
   float bc = Vector3.Dot(pb,pc);
   float cc = Vector3.Dot(pc,pc);
   
   if (bc * ac - cc * ab < 0.0f) return false;
   
   float bb = Vector3.Dot(b,b);
   
   if (ab * bc - ac * bb < 0.0f) return false;
   
   return true;
}


Below is a method of intersecting a line made by two vectors. The intersection point can also be computed. The method will return false if no intersection occurs.
Method also very useful for performing ray-triangle intersections.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
// for triangle a-b-c, intersect the line made by p-q and store intersection point in r
// returns true if intersected, or false if no intersection occurs
public static boolean intersectLineTriangle(Vector3 p, Vector3 q, Vector3 a, Vector3 b, Vector3 c, Vector3 r) {
   // Bring points to their respective coordinate frame
   Vector3 pq = Vector3.subtract(q, p);
   Vector3 pa = Vector3.subtract(a, p);
   Vector3 pb = Vector3.subtract(b, p);
   Vector3 pc = Vector3.subtract(c, p);
   
   Vector3 m = Vector3.Cross(pq,pc);
   
   float u = Vector3.Dot(pb,m);      
   float v = -Vector3.Dot(pa,m);
   
   if (Math.signum(u) != Math.signum(v)) {
      return false;
   }
   
   // scalar triple product
   float w = Vector3.Dot(pq, Vector3.Cross(pb,pa));
   
   if (Math.signum(u) != Math.signum(w)) {
      return false;
   }
   
   float denom = 1.0f / (u + v + w);
   
   // r = ((u * denom) * a) + ((v * denom) * b) + ((w * denom) * c);
   Vector3 compA = Vector3.multiply(a, u * denom);
   Vector3 compB = Vector3.multiply(b, v * denom);
   Vector3 compC = Vector3.multiply(c, w * denom);
   
   // store result in Vector r
   r.x = compA.x + compB.x + compC.x;
   r.y = compA.y + compB.y + compC.y;
   r.z = compA.z + compB.z + compC.z;
   
   return true;
}


Before we proceed with our next method, we are going to define a Plane in 3D. So what is a plane?

A plane can be considered to be an entity which has a position and a direction that extends to and from infinity. It is very useful in certain intersection tests and with some creativity, it can be used to create interesting bounding volumes in code.

Below is how we will define our Plane

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
public class Plane {
   
   public Vector3 n;
   public float d;
   
   public Plane(Vector3 direction, Vector3 position) {
      this.n = direction;
      this.d = Vector3.Dot(n,position);
   }
}


Notice how we don't store position directly? The precomputed floating point d is actually more useful for us when performing intersection tests against this Plane which will soon become apparent.

Lets create our first intersection test - A line vs a Plane test, below is the code

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
// intersect the line a-b with plane p and store result in q
// returns true or false if intersection is found
public static boolean intersectLinePlane(Plane plane, Vector3 a, Vector3 b, Vector3 q) {
   Vector3 ab = Vector3.subtract(b, a);
   
   float t = (plane.d - Vector3.Dot(plane.n, a)) / Vector3.Dot(plane.n, ab);
   
   // floating point errors common here - use own delta values as needed
   if (t >= -0.0001f && t <= 1.0001f) {
      // q = a + t * ab
      q.set(Vector3.add(a, Vector3.multiply(ab, t)));
     
      return true;
   }
   
   return false;
}


And as always, a cheap method exists to see which side a point lies on the Plane. This can be used to early-out most intersection tests before proceeding with expensive mathematics stuff.

1  
2  
3  
4  
5  
// check to see where the point p lies on plane
public static boolean sideOfPlane(Plane plane, Vector3 p) {
   // some bloody math errors here again, modify with delta values as needed
   return Vector3.Dot(plane.n, p) >= plane.d - 0.001f;  
}


I am going to end this tutorial with something very interesting. A concept of Barycentric coordinates, which is a very powerful tool that can be used for both intersection tests and more importantly interpolation inside a 3D triangle.

For example, lets say you wish to cut a Quad made from two triangles with a line. All easy enough, and now you are left with a problem of generating new UV coordinates for the intersection points. As it turns out, if we have a triangle (A,B,C) that has UV coordinates (UVA,UVB,UVC) we can work out "weight" values u,v,w for triangle A,B,C so that for any point P on or in triangle A,B,C will have new UV coordinates of UVP = UVA * u + UVB * v + UVC * w.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
// compute the barycentric coordinates of triangle a-b-c in regards to point p and store result in references u-v-w respectively
// where u = uvw[0], v = uvw[1], w = uvw[2], make sure array uvw is length 3.
public static void barycentric(Vector3 a, Vector3 b, Vector3 c, Vector3 p, float[] uvw) {
   Vector3 m = Vector3.Cross(Vector3.subtract(b, c), Vector3.subtract(c, a));
   
   float nu;
   float nv;
   float ood;
   
   float x = Math.abs(m.x);
   float y = Math.abs(m.y);
   float z = Math.abs(m.z);
   
   // compute areas of plane with largest projections
   if (x >= y && x >= z) {
      // area of PBC in yz plane
      nu = triArea2D(p.y, p.z, b.y, b.z, c.y, c.z);
      // area of PCA in yz plane
      nv = triArea2D(p.y, p.z, c.y, c.z, a.y, a.z);
      // 1/2*area of ABC in yz plane
      ood = 1.0f / m.x;
   }
   else if (y >= x && y >= z) {
      // project in xz plane
      nu = triArea2D(p.x, p.z, b.x, b.z, c.x, c.z);
      nv = triArea2D(p.x, p.z, c.x, c.z, a.x, a.z);
      ood = 1.0f / -m.y;
   }
   else {
      // project in xy plane
      nu = triArea2D(p.x, p.y, b.x, b.y, c.x, c.y);
      nv = triArea2D(p.x, p.y, c.x, c.y, a.x, a.y);
      ood = 1.0f / m.z;
   }
   
   uvw[0] = nu * ood;
   uvw[1] = nv * ood;
   uvw[2] = 1.0f - uvw[0] - uvw[1];
}

// helper function used to compute triangles barycentric coordinates
public static float triArea2D(float x1, float y1, float x2, float y2, float x3, float y3) {
   return (x1 - x2) * (y2 - y3) - (x2 - x3) * (y1 - y2);  
}


Like mentioned above, I've used the same methods to create two Editor extensions for Unity in C#, one being a Slicer Framework (ability to slice objects) and another a Decal Framework (ability to place decals on any object surface). More details if interested can be found in my blog!

Being a Java coder by heart I thought this would be a good place to share some of the source, and hopefully some of you readers will find it useful for your applications!

Any feedback, comments, critics are all welcome  Grin
30  Discussions / Miscellaneous Topics / Re: Dota 2 giveaway ;) on: 2013-03-06 13:06:33
Because my pudge play is amazing!  Grin
Pages: [1] 2 3 4
 
Archive (335 views)
2017-04-27 17:45:51

buddyBro (533 views)
2017-04-05 03:38:00

CopyableCougar4 (975 views)
2017-03-24 15:39:42

theagentd (1011 views)
2017-03-24 15:32:08

Rule (991 views)
2017-03-19 12:43:22

Rule (972 views)
2017-03-19 12:42:17

Rule (968 views)
2017-03-19 12:36:21

theagentd (1068 views)
2017-03-16 05:07:07

theagentd (982 views)
2017-03-15 22:37:06

theagentd (758 views)
2017-03-15 22:32:18
List of Learning Resources
by elect
2017-03-13 14:05:44

List of Learning Resources
by elect
2017-03-13 14:04:45

SF/X Libraries
by philfrei
2017-03-02 08:45:19

SF/X Libraries
by philfrei
2017-03-02 08:44:05

SF/X Libraries
by SkyAphid
2017-03-02 06:38:56

SF/X Libraries
by SkyAphid
2017-03-02 06:38:32

SF/X Libraries
by SkyAphid
2017-03-02 06:38:05

SF/X Libraries
by SkyAphid
2017-03-02 06:37:51
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!