What a Java Novice Does

Tutorials concerning the OpenGL® ES cross-platform API for full-function 2D and 3D graphics on the Google-Android platform.

What a Java Novice Does

Postby seed » Tue May 04, 2010 2:14 pm

This is what a Java novice does:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.         static public float[] add(float[] v1, float[] v2) {
  2.                 float[] result = new float[3];
  3.                
  4.                 result[0] = v1[0]+v2[0];
  5.                 result[1] = v1[1]+v2[1];
  6.                 result[2] = v1[2]+v2[2];
  7.                
  8.                 return result;
  9.         }
  10.  
  11.         static public float[] scale(float[] v1, float s)
  12.         {
  13.                 float[] v = new float[3];
  14.                
  15.                 v[0] = v1[0] * s;
  16.                 v[1] = v1[1] * s;
  17.                 v[2] = v1[2] * s;
  18.                
  19.                 return v;
  20.         }
  21.  
  22.         static public float[] normalize(float[] v1)
  23.         {
  24.                 float length = length(v1);
  25.                 float[] v = new float[3];
  26.                
  27.                 if (length != 0)
  28.                 {
  29.                         v[0] = v1[0] / length;
  30.                         v[1] = v1[1] / length;
  31.                         v[2] = v1[2] / length;
  32.                 }
  33.                
  34.                 return v;
  35.         }
  36.  
  37.         static public float dot_product(float[] v, float[] w) {
  38.                 float result;
  39.                
  40.                 result = v[0]*w[0]+v[1]*w[1]+v[2]*w[2];
  41.                
  42.                 return result;
  43.         }
  44.        
  45.         static public float[] reflect(float[] v1, float[] v2) {
  46.                 float l = length(v1);
  47.                 float dot;
  48.                 float[] result = new float[3];
  49.                
  50.                 v1 = normalize(v1);
  51.                 v2 = normalize(v2);
  52.                 dot = 2*dot_product(inverse(v1),v2);
  53.                 v2 = scale(v2,dot);
  54.                 result = add(v1,v2);
  55.                 result = scale(result,l);
  56.                
  57.                 return result;
  58.         }
  59.  
  60.  
Parsed in 0.035 seconds, using GeSHi 1.0.8.4


I am that novice, new to Java and smitten with the idea that you don't need to delete stuff. Funny, that as an embedded software engineer in real life, I am constantly worrying about deterministic memory allocation.

Anyway, do the above in enough places and your nice little opengl app that is running smoothly at 30+ frames a second experiences 80+ msec hickups every couple seconds when the GC runs.

The question is, what is the best way to re-write the above? Most of this is really straightforward to fix. Here are all the new functions except for reflect which is where my question lies.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.         static public void add(float[] result, float[] v1, float[] v2) {
  2.                 result[0] = v1[0]+v2[0];
  3.                 result[1] = v1[1]+v2[1];
  4.                 result[2] = v1[2]+v2[2];
  5.         }
  6.        
  7.         static public void scale(float[] result, float[] v1, float s)
  8.         {
  9.                 result[0] = v1[0] * s;
  10.                 result[1] = v1[1] * s;
  11.                 result[2] = v1[2] * s;
  12.         }
  13.        
  14.         static public void normalize(float[] v, float[] v1)
  15.         {
  16.                 float length = length(v1);
  17.                
  18.                 if (length != 0)
  19.                 {
  20.                         v[0] = v1[0] / length;
  21.                         v[1] = v1[1] / length;
  22.                         v[2] = v1[2] / length;
  23.                 }
  24.         }
  25.  
  26.         static public float dot_product(float[] v, float[] w) {
  27.                 float result;
  28.                
  29.                 result = v[0]*w[0]+v[1]*w[1]+v[2]*w[2];
  30.                
  31.                 return result;
  32.         }
Parsed in 0.033 seconds, using GeSHi 1.0.8.4


Now with reflect, I need some local objects to do my work. But I don't want to new them in the function and I wasn't sure how to handle it. Since this is part of a static class, I did the following:


Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.                
  2.         static float[] reflect_v1 = new float[3];
  3.         static float[] reflect_v2 = new float[3];
  4.         static float[] reflect_v3 = new float[3];
  5.         static public void reflect(float[] result, float[] v1, float[] v2) {
  6.                 float l = length(v1);
  7.                 float ratio;
  8.                 float dot;
  9.                
  10.                 normalize(reflect_v1,v1);
  11.                 normalize(reflect_v2,v2);
  12.                 dot = dot_product(inverse(reflect_v1),reflect_v2);
  13.                 scale(reflect_v2,reflect_v2,dot);
  14.                 add(reflect_v3,reflect_v1,reflect_v2);
  15.                 ratio = length(reflect_v1);
  16.                 scale(reflect_v3,reflect_v3,l*ratio);
  17.                 copy(result,reflect_v3);
  18.         }
Parsed in 0.035 seconds, using GeSHi 1.0.8.4


I think this is really efficient and doesn't cause any GC but maybe I am wrong. Also, doing this makes the function so that it is not re-entrant. This is not an issue for my app, but it makes the class a little less generally useful.

Is there a better way to handle needing local objects but not wanting to have them collected by the GC?


Note, you might have figured out that "inverse", which is not shown but only called, has not yet been rewritten. I am rewriting stuff one at a time to make sure I am not lost trying to figure out any bugs I create in the rewrite.
Visit Exit 4 Gaming - http://www.exit4games.com/
Home of LavaBall - http://exit4games.com/?page_id=3
Home of Rebound - http://exit4games.com/?page_id=138
Home of Tap Crazy - http://exit4games.com/?page_id=219
Download "Caveman Pool" From the Market Today!
seed
Senior Developer
Senior Developer
 
Posts: 103
Joined: Mon Mar 15, 2010 3:22 pm

Top

Postby zorro » Tue May 04, 2010 3:01 pm

You can make a class called let's say MathUtil and put there all your functions and local variables for 'inside work'. In your functions, make sure to not have any new variables, just use the class members. Then create one MathUtil object and use it across the entire application. That should be efficient.
User avatar
zorro
Experienced Developer
Experienced Developer
 
Posts: 71
Joined: Mon Aug 10, 2009 3:11 pm
Location: Romania

Postby seed » Tue May 04, 2010 4:18 pm

zorro wrote:You can make a class called let's say MathUtil and put there all your functions and local variables for 'inside work'. In your functions, make sure to not have any new variables, just use the class members. Then create one MathUtil object and use it across the entire application. That should be efficient.


Thanks for your input.

OK. Again, as a Java novice, is it just objects created in a function that cause GC, or does any variable in the function cause GC? For example, does this cause GC?

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. public float length(float[] v)
  2. {
  3.    float len;
  4.  
  5.    len = Math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  6.  
  7.    return len;
  8. }
  9.  
Parsed in 0.036 seconds, using GeSHi 1.0.8.4

... or do I need to write it like this?

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. float length_len;
  2. public float length(float[] v)
  3. {
  4.    length_len= Math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  5.  
  6.    return length_len;
  7. }
Parsed in 0.036 seconds, using GeSHi 1.0.8.4


Also, regarding having one instance of my class that I use across the entire application, I am not sure how this is much different than just having a static class. For example, my class with the length function above is really like this.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. static public class vector3d
  2. {
  3.    static float length_len;
  4.    public float length(float[] v)
  5.    {
  6.       length_len= Math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  7.  
  8.       return length_len;
  9.    }
  10. }
  11.  
Parsed in 0.037 seconds, using GeSHi 1.0.8.4


... and I call it like this
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. len = vector3d.length(vector);
Parsed in 0.036 seconds, using GeSHi 1.0.8.4


Your suggestion works well if I have multiple threads that each are calling the methods because I can have an object for each thread eliminating re-entrance issues with members, but it makes me need to have access to the object from everywhere in my code, which I think drives me to a singleton, which brings back the re-entrance issues, which is why I am just thinking a static class.

Thoughts?

.
Visit Exit 4 Gaming - http://www.exit4games.com/
Home of LavaBall - http://exit4games.com/?page_id=3
Home of Rebound - http://exit4games.com/?page_id=138
Home of Tap Crazy - http://exit4games.com/?page_id=219
Download "Caveman Pool" From the Market Today!
seed
Senior Developer
Senior Developer
 
Posts: 103
Joined: Mon Mar 15, 2010 3:22 pm

Postby MichaelEGR » Tue May 04, 2010 4:42 pm

You gave an example.. In this case you don't need the local variable.. Your's 1st.. 2nd how it should be

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public float length(float[] v)
  3.  
  4. {
  5.  
  6.    float len;
  7.  
  8.  
  9.  
  10.    len = Math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  11.  
  12.  
  13.  
  14.    return len;
  15.  
  16. }
  17.  
  18.  
Parsed in 0.037 seconds, using GeSHi 1.0.8.4


Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public float length(float[] v)
  3.  
  4. {
  5.  
  6.    return (float)Math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  7.  
  8. }
  9.  
  10.  
Parsed in 0.037 seconds, using GeSHi 1.0.8.4


For methods like inverse, project, and reflect you can A) use a static local temporary vector object or B) unroll things. Here is my Vecmath.project() method. A as you know is not reentrant

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.    public static Tuple3f project(Tuple3f planePos, Vector3f planeNormal, Tuple3f posIn, Tuple3f posOut)
  3.  
  4.    {
  5.  
  6.       // projectVec.sub(posIn, planePos)
  7.  
  8.       float x = posIn.x - planePos.x;
  9.  
  10.       float y = posIn.y - planePos.y;
  11.  
  12.       float z = posIn.z - planePos.z;
  13.  
  14.  
  15.  
  16.       // projectVec.dot(planeNormal)
  17.  
  18.       float distance = x * planeNormal.x + y * planeNormal.y + z * planeNormal.z;
  19.  
  20.  
  21.  
  22.       // posOut.scaleAdd(-distanceD, planeNormal, posIn)
  23.  
  24.       posOut.x = -distance * planeNormal.x + posIn.x;
  25.  
  26.       posOut.y = -distance * planeNormal.y + posIn.y;
  27.  
  28.       posOut.z = -distance * planeNormal.z + posIn.z;
  29.  
  30.  
  31.  
  32.       return posOut;
  33.  
  34.    }
  35.  
  36.  
Parsed in 0.039 seconds, using GeSHi 1.0.8.4


For more wide spread usage of local variables you can take a look at JStackAlloc and I do believe there is also object recycling functionality in Javolution.
Founder & Principal Architect; EGR Software LLC
http://www.typhonrt.org
http://www.egrsoftware.com
User avatar
MichaelEGR
Senior Developer
Senior Developer
 
Posts: 147
Joined: Thu Jan 21, 2010 5:30 am
Location: San Francisco, CA

Postby seed » Tue May 04, 2010 7:25 pm

MichaelEGR wrote:You gave an example.. In this case you don't need the local variable.. Your's 1st.. 2nd how it should be...


Point taken ;)


MichaelEGR wrote:For methods like inverse, project, and reflect you can A) use a static local temporary vector object or B) unroll things. Here is my Vecmath.project() method. A as you know is not reentrant


Wow, unroll things is a nightmare. But, it will definitely work. Obviously because you have done it. I hate (A) because it is not reentrant.

How about option (C), add a simple stack.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. public class Vector
  2. {
  3.         public x,y,z;
  4.        
  5.         // Static stack stuff
  6.         private static final STACK_SIZE = 100;
  7.         private static Vector[] stack;
  8.         private static boolean initialized = false;
  9.         private static int stack_index = 0;
  10.        
  11.         // Stack allocation and freeing
  12.         public static Vector alloc()
  13.         {
  14.                 if (!initialized)
  15.                         init();
  16.                
  17.                 return stack[stack_index++];
  18.         }      
  19.        
  20.         public static void free()
  21.         {
  22.                 if (!initialized)
  23.                         init();
  24.                
  25.                 if (stack_index > 0)
  26.                         stack_index--;
  27.         }
  28.        
  29.         private void init()
  30.         {
  31.                 stack = new Vector[STACK_SIZE];
  32.                 for (int i=0; i<STACK_SIZE; i++)
  33.                 {
  34.                         stack[i] = new Vector();
  35.                 }
  36.                 initialized = true;
  37.         }
  38.        
  39.         // Constructor
  40.         public Vector()
  41.         {
  42.                 x = 0;
  43.                 y = 0;
  44.                 z = 0;
  45.         }
  46.        
  47.         // Static math methods for manipulating Vectors
  48.         static public void add(Vector v1, Vector v2, Vector v3)
  49.         {
  50.                 v1.x = v2.x + v3.x;
  51.                 v1.y = v2.y + v3.y;
  52.                 v1.z = v2.z + v3.z;
  53.         }
  54.        
  55.         static public void copy(Vector v1, Vector v2)
  56.         {
  57.                 v1.x = v2.x;
  58.                 v1.y = v2.y;
  59.                 v1.z = v2.z;
  60.         }
  61.        
  62.         static public void reflect(Vector result, Vector dir, Vector normal)
  63.         {
  64.                 float len;
  65.                 float ratio;
  66.                 float dot;
  67.                
  68.                 Vector v1 = alloc();
  69.                 Vector v2 = alloc();
  70.                 Vector v3 = alloc();
  71.                
  72.                 len = length(dir);
  73.                 normalize(v1,dir);
  74.                 normalize(v2,normal);
  75.                 inverse(v3,v1);
  76.                 dot = dot_product(v3,v2);
  77.                 scale(v2,v2,dot);
  78.                 add(result,v1,v2);
  79.                 ratio = length(v1);
  80.                 scale(result,result,len*ratio);
  81.                
  82.                 free();
  83.                 free();
  84.                 free();
  85.                
  86.                 return result;
  87.         }
  88.  
  89.         static public float length(Vector v1)
  90.         {
  91.                 return = Math.sqrt(v1.x*v1.x + v1.y*v1.y + v1.z*v1.z);
  92.         }
  93.        
  94.         static public void normalize(Vector result, Vector v1)
  95.         {
  96.                 float len = length(v1);
  97.                 if (length != 0)
  98.                 {
  99.                         result.x = v1.x / len;
  100.                         result.y = v1.y / len;
  101.                         result.z = v1.z / len;
  102.                 }
  103.         }
  104.        
  105.         // Written with temp vector in order to work when result is also one of  
  106.         // other two parameters
  107.         static public void cross_product(Vector result, Vector v1, Vector v2)
  108.         {
  109.                 Vector temp = alloc();
  110.                
  111.                 temp.x = v1.y * v2.z - v1.z * v2.y;
  112.                 temp.y = v1.z * v2.x - v1.x * v2.z;
  113.                 temp.z = v1.x * v2.y - v1.y * v2.x;
  114.                 result.copy(temp);
  115.                
  116.                 free();
  117.                
  118.                 return result;
  119.         }
  120.        
  121.         static public float dot_product(Vector v, Vector w)
  122.         {
  123.                 return( v.x * w.x + v.y * w.y + v.z * w.z);
  124.         }
  125.        
  126. }
  127.  
Parsed in 0.046 seconds, using GeSHi 1.0.8.4


Edit - not sure why I had two classes. One Vector class is fine. I suck at Java.

Or model after something like the following which does the same thing but with a new stack per thread.

http://code.google.com/p/jmonkeyengine/ ... pVars.java
Visit Exit 4 Gaming - http://www.exit4games.com/
Home of LavaBall - http://exit4games.com/?page_id=3
Home of Rebound - http://exit4games.com/?page_id=138
Home of Tap Crazy - http://exit4games.com/?page_id=219
Download "Caveman Pool" From the Market Today!
seed
Senior Developer
Senior Developer
 
Posts: 103
Joined: Mon Mar 15, 2010 3:22 pm

Postby seed » Wed May 05, 2010 2:18 pm

The code above was written in a text editor and is riddled with bugs. But, I implemented this last night and it worked well. I still need to turn a lot of my variables into Vector's that were previously float[3] but for the ones I have converted already, the new class is working great. Nested calls work fine with stack allocated temp Vectors. I will post the good code at some point.

My next step is to do the same thing with my 3 and 4 dimensional matrixes and my quarternions. In the end, I think I will get rid of a bunch of GC.

Thanks for talking and getting me thinking.
Visit Exit 4 Gaming - http://www.exit4games.com/
Home of LavaBall - http://exit4games.com/?page_id=3
Home of Rebound - http://exit4games.com/?page_id=138
Home of Tap Crazy - http://exit4games.com/?page_id=219
Download "Caveman Pool" From the Market Today!
seed
Senior Developer
Senior Developer
 
Posts: 103
Joined: Mon Mar 15, 2010 3:22 pm

Top

Postby MichaelEGR » Fri May 07, 2010 1:51 am

For a utility class with static vector math methods I think it's best to do the unrolling approach as this code is going to be called a lot. It doesn't matter if it's ugly as long as there are no bugs and such; that is why I leave comments with the actual vector object methods that would be called instead of the unrolled code. The fewer internal method calls to a given vector math method the better. Think of the method overhead for billboarding and such when using an inverse matrix method which can be called each time a billboard is rendered.

IE get stack allocated vectors, set the vector values, then call methods on the stack allocated vectors then calling the free methods. Look at your reflect method as it has 14 method calls. This will slow down your code.

Obviously I don't recommend unrolling for everything as OO is nice, but in this case it's pertinent for high throughput.

---

Technically the stack you created is simple and works, but is not thread safe as the pool is shared between X threads.

You can look into ThreadLocal:
http://java.sun.com/javase/6/docs/api/j ... Local.html
And perhaps create and access your stack that way such that each thread will have its own object stack.

---

For wide spread local object usage JStackAlloc is a better option than your home rolled solution.
http://www.javagaming.org/index.php/topic,18843.0.html

There are other options too like I mentioned I'm sure there is a pool solution in Javolution. There are likely others as well.

---

One last general comment you may want to use a javax.vecmath implementation as rolling your own Vector and Matrix classes will make your code incompatible to a bunch of other math related Java code. While various Java 3D engines for instance started with their own implementations (Java Monkey Engine / JME) is an example if you want to interface with 3rd party code you'll have to create a bridge to marshal data from your vector format to likely javax.vecmath (most widely used vecmath API/library).

Here is a link to an independent version; yes created a long time ago!
http://www.objectclub.jp/download/vecmath_e

I actually have a modified the version above over the years and will likely release mine MIT licensed when I release TyphonRT.
Founder & Principal Architect; EGR Software LLC
http://www.typhonrt.org
http://www.egrsoftware.com
User avatar
MichaelEGR
Senior Developer
Senior Developer
 
Posts: 147
Joined: Thu Jan 21, 2010 5:30 am
Location: San Francisco, CA

Postby seed » Fri May 07, 2010 1:25 pm

I agree with EVERYTHING you said above. But, for me right now, there is some definite time management issues. I am not having any performance issues with this code other than the GC stuff, so I don't think I need to spend my resources on any of the very wise optimizations that you suggest. I am not designing a general game engine like you are, but a specific one for a specific application. So I need to optimize only to how it effects the overall performance my app.

But, for those browsing this post, Michael is right and I am wrong. Listen to him, not me.

I am currently working a full time job, I am in the middle of getting lawyered up for a copywrite related law suit with a huge game manufacturer, I have three kids and a wife to consider, and I am trying to put in three or four hours every night learning this stuff.

I am really excited because I strongly believe that I have a great game on my hands. Even the early alpha build kicks ass. But I need to get it done so how I spend my time is really important. Tradeoffs.

Needless to say, I am really tired:) Your feedback on a lot of my questions has been really helpful. I appreciate it.

Thanks,
Seed
Visit Exit 4 Gaming - http://www.exit4games.com/
Home of LavaBall - http://exit4games.com/?page_id=3
Home of Rebound - http://exit4games.com/?page_id=138
Home of Tap Crazy - http://exit4games.com/?page_id=219
Download "Caveman Pool" From the Market Today!
seed
Senior Developer
Senior Developer
 
Posts: 103
Joined: Mon Mar 15, 2010 3:22 pm

Postby seed » Fri May 07, 2010 2:23 pm

For those reading, this is the current implementation of my 3d vector class.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. public class Vector3
  2.  
  3. {
  4.  
  5.        
  6.  
  7.     public float x,y,z;
  8.  
  9.    
  10.  
  11.     // Static stack stuff
  12.  
  13.     private static int STACK_SIZE = 100;
  14.  
  15.     private static Vector3[] stack;
  16.  
  17.     private static boolean initialized = false;
  18.  
  19.     private static int stack_index = 0;
  20.  
  21.      
  22.  
  23.     // Stack allocation and freeing
  24.  
  25.     public static Vector3 alloc()
  26.  
  27.     {
  28.  
  29.          if (!initialized)
  30.  
  31.               init();
  32.  
  33.          
  34.  
  35.          return stack[stack_index++];
  36.  
  37.     }    
  38.  
  39.      
  40.  
  41.     public static void free()
  42.  
  43.     {
  44.  
  45.          if (!initialized)
  46.  
  47.               init();
  48.  
  49.          
  50.  
  51.          if (stack_index > 0)
  52.  
  53.               stack_index--;
  54.  
  55.     }
  56.  
  57.      
  58.  
  59.     private static void init()
  60.  
  61.     {
  62.  
  63.          stack = new Vector3[STACK_SIZE];
  64.  
  65.          for (int i=0; i<STACK_SIZE; i++)
  66.  
  67.          {
  68.  
  69.               stack[i] = new Vector3();
  70.  
  71.          }
  72.  
  73.          initialized = true;
  74.  
  75.     }
  76.  
  77.      
  78.  
  79.     // Constructor
  80.  
  81.     public Vector3()
  82.  
  83.     {
  84.  
  85.          x = 0;
  86.  
  87.          y = 0;
  88.  
  89.          z = 0;
  90.  
  91.     }
  92.  
  93.  
  94.  
  95.     public Vector3(float xin, float yin, float zin)
  96.  
  97.     {
  98.  
  99.         x=xin; y=yin; z=zin;
  100.  
  101.     }
  102.  
  103.        
  104.  
  105.     // Static math methods for manipulating Vectors
  106.  
  107.     static public void add(Vector3 v1, Vector3 v2, Vector3 v3)
  108.  
  109.     {
  110.  
  111.          v1.x = v2.x + v3.x;
  112.  
  113.          v1.y = v2.y + v3.y;
  114.  
  115.          v1.z = v2.z + v3.z;
  116.  
  117.     }
  118.  
  119.      
  120.  
  121.     static public void subtract(Vector3 v1, Vector3 v2, Vector3 v3)
  122.  
  123.     {
  124.  
  125.          v1.x = v2.x - v3.x;
  126.  
  127.          v1.y = v2.y - v3.y;
  128.  
  129.          v1.z = v2.z - v3.z;
  130.  
  131.     }
  132.  
  133.      
  134.  
  135.     static public void copy(Vector3 v1, Vector3 v2)
  136.  
  137.     {
  138.  
  139.          v1.x = v2.x;
  140.  
  141.          v1.y = v2.y;
  142.  
  143.          v1.z = v2.z;
  144.  
  145.     }
  146.  
  147.    
  148.  
  149.     static public float[] to_float(Vector3 v)
  150.  
  151.     {
  152.  
  153.         float[] result = new float[3];
  154.  
  155.        
  156.  
  157.         result[0] = v.x;
  158.  
  159.         result[1] = v.y;
  160.  
  161.         result[2] = v.z;
  162.  
  163.        
  164.  
  165.         return result;
  166.  
  167.     }
  168.  
  169.      
  170.  
  171.     static public Vector3 to_Vector3(float[] f)
  172.  
  173.     {
  174.  
  175.         Vector3 result = new Vector3(f[0],f[1],f[2]);
  176.  
  177.        
  178.  
  179.         return result;
  180.  
  181.     }
  182.  
  183.      
  184.  
  185.     static public void reflect(Vector3 result, Vector3 dir, Vector3 normal, float damp)
  186.  
  187.     {
  188.  
  189.          float len;
  190.  
  191.          float ratio;
  192.  
  193.          float dot;
  194.  
  195.          
  196.  
  197.          Vector3 v1 = alloc();
  198.  
  199.          Vector3 v2 = alloc();
  200.  
  201.          Vector3 v3 = alloc();
  202.  
  203.          
  204.  
  205.          len = length(dir);
  206.  
  207.          normalize(v1,dir);
  208.  
  209.          normalize(v2,normal);
  210.  
  211.          inverse(v3,v1);
  212.  
  213.          dot = (1+damp)*dot_product(v3,v2);
  214.  
  215.          scale(v2,v2,dot);
  216.  
  217.          add(result,v1,v2);
  218.  
  219.          ratio = length(v1);
  220.  
  221.          scale(result,result,len*ratio);
  222.  
  223.          
  224.  
  225.          free();
  226.  
  227.          free();
  228.  
  229.          free();
  230.  
  231.     }
  232.  
  233.    
  234.  
  235.     static public void inverse(Vector3 v1, Vector3 v2)
  236.  
  237.     {
  238.  
  239.          v1.x = -v2.x;
  240.  
  241.          v1.y = -v2.y;
  242.  
  243.          v1.z = -v2.z;
  244.  
  245.     }
  246.  
  247.    
  248.  
  249.     static public void scale(Vector3 v1, Vector3 v2, float s)
  250.  
  251.     {
  252.  
  253.         v1.x = v2.x * s;
  254.  
  255.         v1.y = v2.y * s;
  256.  
  257.         v1.z = v2.z * s;
  258.  
  259.     }
  260.  
  261.  
  262.  
  263.     static public float length(Vector3 v1)
  264.  
  265.     {
  266.  
  267.          return (float) Math.sqrt(v1.x * v1.x + v1.y * v1.y + v1.z * v1.z);
  268.  
  269.     }
  270.  
  271.      
  272.  
  273.     static public void normalize(Vector3 result, Vector3 v1)
  274.  
  275.     {
  276.  
  277.          float len = length(v1);
  278.  
  279.          if (len != 0)
  280.  
  281.          {
  282.  
  283.               result.x = v1.x / len;
  284.  
  285.               result.y = v1.y / len;
  286.  
  287.               result.z = v1.z / len;
  288.  
  289.          }
  290.  
  291.     }
  292.  
  293.      
  294.  
  295.     // Written with temp vector in order to work when result is also one of  
  296.  
  297.     // other two parameters
  298.  
  299.     static public void cross_product(Vector3 result, Vector3 v1, Vector3 v2)
  300.  
  301.     {
  302.  
  303.          Vector3 temp = alloc();
  304.  
  305.          
  306.  
  307.          temp.x = v1.y * v2.z - v1.z * v2.y;
  308.  
  309.          temp.y = v1.z * v2.x - v1.x * v2.z;
  310.  
  311.          temp.z = v1.x * v2.y - v1.y * v2.x;
  312.  
  313.          copy(result,temp);
  314.  
  315.          
  316.  
  317.          free();
  318.  
  319.     }
  320.  
  321.      
  322.  
  323.     static public float dot_product(Vector3 v, Vector3 w)
  324.  
  325.     {
  326.  
  327.          return( v.x * w.x + v.y * w.y + v.z * w.z);
  328.  
  329.     }
  330.  
  331. }
Parsed in 0.053 seconds, using GeSHi 1.0.8.4


...and here is some sample code that uses it. Note that I am using the to_float and to_Vector3 functions because I haven't yet converted all of my variables to Vector3's. This allows me to change a little at a time and make sure it still works.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.     // Called once a frame for movement for this object.
  3.  
  4.     public void move()
  5.  
  6.         {
  7.  
  8.                 vector3d.insertionResult result;
  9.  
  10.                 float l,tl;  // Length variables
  11.  
  12.                 float[] adjust = LavaBall.getSense();
  13.  
  14.        
  15.  
  16.                 Vector3 mvel = Vector3.alloc();
  17.  
  18.                 Vector3 mpos = Vector3.alloc();
  19.  
  20.                 Vector3 temp = Vector3.alloc();
  21.  
  22.                
  23.  
  24.                 // copy position and velocity to local variables.
  25.  
  26.                 // FIXME - change to time based rather than frame based movement.
  27.  
  28.                 Vector3.copy(mpos,position);
  29.  
  30.                 Vector3.copy(mvel,velocity);
  31.  
  32.  
  33.  
  34.                 // Save the length of the velocity.  We use later to restore the velocity.
  35.  
  36.                 l = Vector3.length(velocity);
  37.  
  38.                                
  39.  
  40.                 // Determine if any collisions by testing against the bsp.  Bsp will return a ratio
  41.  
  42.                 // of your movement distance for when the first insertion into the world surfaces takes
  43.  
  44.                 // place.
  45.  
  46.                 // If there is an intersection, then reflect the move and move the remaining distance.
  47.  
  48.                 result = World.bsp.testInsertion(Vector3.to_float(mpos), Vector3.to_float(mvel), radius,null, sequence_number++);
  49.  
  50.                 while(result.intersection)
  51.  
  52.                 {
  53.  
  54.                         // Shorten the movement vector by the ratio of the distance traveled.
  55.  
  56.                         Vector3.scale(temp, mvel, result.dist);
  57.  
  58.                         Vector3.add(mpos,mpos,temp);
  59.  
  60.  
  61.  
  62.                         // Subtract it from the overall movement vector.  This is the movement
  63.  
  64.                         // left to be made this frame.
  65.  
  66.                         Vector3.subtract(mvel,mvel,temp);
  67.  
  68.  
  69.  
  70.                         // Reflect the velocity based on the normal of collision.  Reflection is not
  71.  
  72.                         // perfectly elastic.  The constant at the end slows the outgoing velocity.
  73.  
  74.                         // Since we are only operating on the local velocity vector, we need to find
  75.  
  76.                         // the ratio of that velocity reduction and apply it to the l variable that will
  77.  
  78.                         // be used later to restore the member velocity variable.
  79.  
  80.                         tl = Vector3.length(mvel);
  81.  
  82.                         Vector3.reflect(mvel,mvel,Vector3.to_Vector3(result.normal),0.3f);
  83.  
  84.                         l = l * (Vector3.length(mvel)/tl);
  85.  
  86.                      
  87.  
  88.                         // Test for another insertion on the next bit of our movement.
  89.  
  90.                         result = World.bsp.testInsertion(Vector3.to_float(mpos), Vector3.to_float(mvel), radius,null, sequence_number++);
  91.  
  92.                 }
  93.  
  94.                                
  95.  
  96.                 // Add in the last bit of non-colliding movement
  97.  
  98.                 Vector3.add(mpos,mpos,mvel);
  99.  
  100.  
  101.  
  102.                 // Restore velocity
  103.  
  104.                 Vector3.normalize(mvel,mvel);
  105.  
  106.                 Vector3.scale(velocity, mvel, l);
  107.  
  108.                
  109.  
  110.                 // Restore position
  111.  
  112.                 Vector3.copy(position,mpos);           
  113.  
  114.                                
  115.  
  116.                 // New acceleration based on sensor orientation
  117.  
  118.                
  119.  
  120.                 // Start with the normalized orientation acceleration.  
  121.  
  122.                 acceleration.x=adjust[0];
  123.  
  124.                 acceleration.y=adjust[1];
  125.  
  126.                 acceleration.z=adjust[2];
  127.  
  128.  
  129.  
  130.                 // Scale it to something that makes sense for this world.
  131.  
  132.                 Vector3.normalize(acceleration,acceleration);
  133.  
  134.                 Vector3.scale(acceleration,acceleration, 0.004f);
  135.  
  136.                
  137.  
  138.                 // Update the velocity with the acceleration
  139.  
  140.                 Vector3.add(velocity,velocity,acceleration);
  141.  
  142.                
  143.  
  144.                 Vector3.free();  // temp
  145.  
  146.                 Vector3.free();  // mpos
  147.  
  148.                 Vector3.free();  // mvel
  149.  
  150.  
  151.  
  152.         }
Parsed in 0.045 seconds, using GeSHi 1.0.8.4
Visit Exit 4 Gaming - http://www.exit4games.com/
Home of LavaBall - http://exit4games.com/?page_id=3
Home of Rebound - http://exit4games.com/?page_id=138
Home of Tap Crazy - http://exit4games.com/?page_id=219
Download "Caveman Pool" From the Market Today!
seed
Senior Developer
Senior Developer
 
Posts: 103
Joined: Mon Mar 15, 2010 3:22 pm

Re: What a Java Novice Does

Postby seed » Tue May 18, 2010 7:54 pm

I finally finished all of my removing bad java coder stuff. My application now runs with zero real-time GC and it is running blazingly fast! Woop! Thanks for all the help and suggestions.
Visit Exit 4 Gaming - http://www.exit4games.com/
Home of LavaBall - http://exit4games.com/?page_id=3
Home of Rebound - http://exit4games.com/?page_id=138
Home of Tap Crazy - http://exit4games.com/?page_id=219
Download "Caveman Pool" From the Market Today!
seed
Senior Developer
Senior Developer
 
Posts: 103
Joined: Mon Mar 15, 2010 3:22 pm

Re: What a Java Novice Does

Postby torpor » Sat May 22, 2010 11:37 pm

This looks really nice .. I'm learning a lot from this!
torpor
Junior Developer
Junior Developer
 
Posts: 13
Joined: Tue Feb 24, 2009 12:23 pm

Top

Return to Android 2D/3D Graphics - OpenGL Tutorials

Who is online

Users browsing this forum: No registered users and 1 guest