Presing Posted July 23, 2011 Posted July 23, 2011 (edited) Then what you think to go with same stuff with little changes. Like a green triangle but his lines are not full like this _ _ for one way and another way will be with full lines ___. Problem with this stuff is how big this symbols are. If they are not big enough breaks in the line will be very small and hard to see. Edited July 23, 2011 by Presing Rocket brigade who retired F-117
RvEYoda Posted July 23, 2011 Author Posted July 23, 2011 Then what you think to go with same stuff with little changes. Like a green triangle but his lines are not full like this _ _ for one way and another way will be with full lines ___. Problem with this stuff is how big this symbols are. If they are not big enough breaks in the line will be very small and hard to see. Yeah it's not an entirely bad idea but it will be difficult to do well since gear runs virtually any resolution and size, and must adapt to such conditions S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'
RvEYoda Posted July 24, 2011 Author Posted July 24, 2011 (edited) Been fooling around with optmizing a little bit of everything, and it resulted in (another) complete rewrite of the graphics engine of GEAR, and some other stuff... * Implemented my own transformation matrices and my own opengl-ish matrix stack, cause going through JNI (and in fact OpenGL in general) is too slow ;). Also OpenGL is single threaded while mine could be run from any number of threads. (So all interactions I have with opengl are 1. send finished transf matrix, 2. Send color, 3. send geometry). So now I feel like I've optimized this to death (check image below for cpu load results at 60 fps, 0.43% cpu avg ^^). As it turns out, the most expensive operations by far are transferring my finished transformation matrices and performing rotational transformations (becaue of Java's fall back to software cos/sine/tan). There for I .... * Implemented my own cosine/sine/tan functions :P (approx 3x faster than java in the best conditions, I use a quick range reduction to +- 90 deg and then use a simple taylor, well maclaurin to be precise, polynomial that is accurate to approx 6th decimal (enough for gear graphics purposes)) The reason Java is slow is because outside [-pi/4,pi/4] it no longer uses machine cos/sine directly but instead goes through a lot of code (I don't know why theirs is so slow) to make sure their answers are basically exact to n bits by some formal definition, something we don't really require here. I experimented with a few different approaches to get around this. The first was to make a lookup table and then add some interpolation, but this was waaay too slow, probably because it had to go fetch stuff from the main ram each time for any tables larger than what the CPU cache allowed. The second attempt (seen also in the code below) was to go through JNI to call standard C cos/sin in Math.h, well turns out the jni overhead was too much and the result was a function about as fast as the java built in ones (so no gain there) with the obvious lack of precision. Thirdly I decided to simply implement my own, the code can be seen below: (turns out a direct tan maclaurin expansion fails totally, so I used a more blunt approach and just divided the sine expansion with the cos one. It's not fast though and I basically don't use that, but the sine and cos are much faster than their Java built in counterparts so when I need to rotate some graphical object I only use them and never Java's built in ones) package sloppymath; import gear.Native; public abstract class SloppyMath { private static final float PI = (float) Math.PI; private static final float HALFPI = (float) (Math.PI / 2.0); private static final double TWOPIDOUBLE = 2.0 * Math.PI; private static final double QUARTERPI = Math.PI / 4; /*! * Sucks, and only for testing (not used atm). * Not as precise as standard java cos and slighty slower, due to JNI overhead. */ public final static float sinJNI(final float rads) { return Native.sin(rads); } /*! * Sucks, and only for testing (not used atm). * Not as precise as standard java cos and slighty slower, due to JNI overhead. */ public final static float cosJNI(final float rads) { return Native.cos(rads); } /*! * Significantly faster than java sin. * Precision is about last decimal wrong for single precision floats */ public final static float sinTaylor9f(final float r) { // Get within +-180º (use doubles here) float r1 = (float) (r - TWOPIDOUBLE * (int) ((r < 0 ? -0.5 : 0.5) + r / TWOPIDOUBLE)), s = 1; // Get within +-90º if (r1 < -HALFPI) { r1 += PI; s = -1; } else if (r1 > HALFPI) { r1 -= PI; s = -1; } return s * (// +r1 - r1 * r1 * r1 / 6.0f + r1 * r1 * r1 * r1 * r1 / 120.0f - r1 * r1 * r1 * r1 * r1 * r1 * r1 / 5040.0f + r1 * r1 * r1 * r1 * r1 * r1 * r1 * r1 * r1 / 362880.0f); } /*! * Significantly faster than java cos. * Precision is about last decimal wrong for single precision floats */ public final static float cosTaylor8f(final float r) { // Get within +-180º (use doubles here) float r1 = (float) (r - TWOPIDOUBLE * (int) ((r < 0 ? -0.5 : 0.5) + r / TWOPIDOUBLE)), s = 1; // Get within +-90º if (r1 < -HALFPI) { r1 += PI; s = -1; } else if (r1 > HALFPI) { r1 -= PI; s = -1; } return s * (// +1 - r1 * r1 / 2.0f + r1 * r1 * r1 * r1 / 24.0f - r1 * r1 * r1 * r1 * r1 * r1 / 720.0f + r1 * r1 * r1 * r1 * r1 * r1 * r1 * r1 / 40320.0f); } /*! * Faster than java tan on average ((r < QUARTERPI && r > -QUARTERPI) it is slightly slower). * Precision is about last decimal wrong for single precision floats */ public static final float tanTaylor9f(final float r) { // Math.tan is faster for small arguments if (r < QUARTERPI && r > -QUARTERPI) { return (float) Math.tan(r); } // Get within +-180º (use doubles here) float r1 = (float) (r - TWOPIDOUBLE * (int) ((r < 0 ? -0.5 : 0.5) + r / TWOPIDOUBLE)); // Get within +-90º if (r1 < -HALFPI) { r1 += PI; } else if (r1 > HALFPI) { r1 -= PI; } return // (// +r1 - r1 * r1 * r1 / 6.0f + r1 * r1 * r1 * r1 * r1 / 120.0f - r1 * r1 * r1 * r1 * r1 * r1 * r1 / 5040.0f + r1 * r1 * r1 * r1 * r1 * r1 * r1 * r1 * r1 / 362880.0f) / (// +1 - r1 * r1 / 2.0f + r1 * r1 * r1 * r1 / 24.0f - r1 * r1 * r1 * r1 * r1 * r1 / 720.0f + r1 * r1 * r1 * r1 * r1 * r1 * r1 * r1 / 40320.0f); } public static final float abs(final float val) { return val < 0 ? -val : val; } public static final int round(final float val) { return (int) ((val < 0 ? -0.5f : 0.5f) + val); } } Edited July 24, 2011 by =RvE=Yoda S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'
Moa Posted July 24, 2011 Posted July 24, 2011 Looking good Yoda. TCP does have checksum, but this doesn't help if packets are lost completely (depends on whether you make more than one transmission or not - if you only do one transfer then it makes no difference). Should not read back from OpenGL because the transformations are done on the GPU and stored in VRAM. Reading back from VRAM is horrifically expensive. Yeah, Java is slow for trig because it is IEEE compliant (unlike the Intel x87 hardware). You can get even faster math by doing what we used to do in the old days, create lookup tables. These days the RAM use is negligible compared to textures etc. so they are a good option for extreme performance. It sounds like you have your performance good enough as it is already though.
RvEYoda Posted July 24, 2011 Author Posted July 24, 2011 (edited) Looking good Yoda. TCP does have checksum, but this doesn't help if packets are lost completely (depends on whether you make more than one transmission or not - if you only do one transfer then it makes no difference). Should not read back from OpenGL because the transformations are done on the GPU and stored in VRAM. Reading back from VRAM is horrifically expensive. Yeah, Java is slow for trig because it is IEEE compliant (unlike the Intel x87 hardware). You can get even faster math by doing what we used to do in the old days, create lookup tables. These days the RAM use is negligible compared to textures etc. so they are a good option for extreme performance. It sounds like you have your performance good enough as it is already though. Moa, I think you should reread my post :P. Looks like you misunderstood parts of it ^^. If a packet is completely lost that is not a problem imo with the sim-gear link. you will have a gap of 1/30 s instead of 1/60 s, and since I transmit a snapshot of the sim every time there is no need to receive every message. I never read back from VRAM (and I didnt before either). Using OpenGL FFP function calls is quite slow, and with an extra layer of JNI on top of that it is faster to perform on-CPU transformations or go with shaders. There is a quite long post about it here that I started: http://jogamp.org/forum.html. After I finish making all my transformations I make one single call to glLoadMatrixf. As I wrote in my previous post about lookup tables: It seems that if I make them larger than a couple of hundred entries, they arent put into the CPU cache anymore and then it becomes super slow to read them (I tested). So Maybe some intelligent solution with low N would be possible here with smart interpolation. However I have thought about the idea of creating lookup tables of low term taylor series for different cos/sine argument regions. If you have any ideas on how a good lookup implementation should be made though, I would gladly try it. Cos/Sine operations are still almost the biggest performance hit of the entire GEAR application! The biggest hits are (not in any particular order) sine calls, cosine calls, glLoadMatrixf calls, textrenderer calls (which I have made to an absolute minimum) Back to the openGL stuff, I made two classes to perform the math for my 2d graphics: package opengl.matrix2d; import sloppymath.SloppyMath; import com.jogamp.opengl.util.GLBuffers; import java.nio.FloatBuffer; public class Matrix2d { private final static float TODEGREES = 180f / (float) Math.PI; private final FloatBuffer out = GLBuffers.newDirectFloatBuffer(16); private boolean isDirty = true; private float // a11 = 1, a21 = 0, a31 = 0, a41 = 0, a12 = 0, a22 = 1, a32 = 0, a42 = 0, a13 = 0, a23 = 0, a33 = 1, a43 = 0, a14 = 0, a24 = 0, a34 = 0, a44 = 1; public Matrix2d() { out // .put(0, a11).put(1, a21).put(2, a31).put(3, a41) // .put(4, a12).put(5, a22).put(6, a32).put(7, a42) // .put(8, a13).put(9, a23).put(10, a33).put(11, a43) // .put(12, a14).put(13, a24).put(14, a34).put(15, a44); // } public final void loadIdentity() { a11 = 1; a12 = 0; /* a13 = 0; */ a14 = 0; a21 = 0; a22 = 1; /* a23 = 0; */ a24 = 0; /* a31 = 0; a32 = 0; a33 = 1; a34 = 0; a41 = 0; a42 = 0; a43 = 0; a44 = 1; */ isDirty = true; } public final void rotateZ(final float angDeg) { // multiplying A*B the previous matrix (A) with the rotational matrix B { cos -sin // sin cos // 1 // 1 } // Changes all elements in the first 2 cols final float cos = SloppyMath.cosTaylor8f(-angDeg / TODEGREES), sin = SloppyMath.sinTaylor9f(-angDeg / TODEGREES), na11 = a11 * cos + a12 * sin, na21 = a21 * cos + a22 * sin/*, na31 = a31 * cos + a32 * sin, na41 = a41 * cos + a42 * sin*/; a12 = -a11 * sin + a12 * cos; a22 = -a21 * sin + a22 * cos; /* a32 = -a31 * sin + a32 * cos; a42 = -a41 * sin + a42 * cos;*/ a11 = na11; a21 = na21; /* a31 = na31; a41 = na41;*/ isDirty = true; } public final void scaleX(final float scale) { a11 *= scale; a21 *= scale; /* a31 *= scale; a41 *= scale;*/ isDirty = true; } public final void scaleY(final float scale) { a12 *= scale; a22 *= scale; /* a32 *= scale; a42 *= scale;*/ isDirty = true; } public final void scaleXY(final float sx, final float sy) { a11 *= sx; a21 *= sx; /* a31 *= sx; a41 *= sx;*/ a12 *= sy; a22 *= sy; /* a32 *= sy; a42 *= sy;*/ isDirty = true; } public final void translateXY(final float dx, final float dy) { a14 += dx * a11 + dy * a12; a24 += dx * a21 + dy * a22; /* a34 += dx * a31 + dy * a32; a44 += dx * a41 + dy * a42;*/ isDirty = true; } public final void translateX(final float dx) { a14 += dx * a11; a24 += dx * a21; /* a34 += dx * a31; a44 += dx * a41;*/ isDirty = true; } public final void translateY(final float dy) { a14 += dy * a12; a24 += dy * a22; /* a34 += dy * a32; a44 += dy * a42;*/ isDirty = true; } public final FloatBuffer copyInto(final FloatBuffer fb) { return fb// .put(0, a11).put(1, a21).put(2, a31).put(3, a41) // .put(4, a12).put(5, a22).put(6, a32).put(7, a42) // .put(8, a13).put(9, a23).put(10, a33).put(11, a43) // .put(12, a14).put(13, a24).put(14, a34).put(15, a44); // } public final FloatBuffer getBuffer() { if (isDirty) { out.put(0, a11).put(1, a21).put(4, a12).put(5, a22).put(10, a33).put(12, a14).put(13, a24); isDirty = false; } return out; } public final void onPush(final Matrix2d nextMatrix) { nextMatrix.a11 = this.a11; nextMatrix.a12 = this.a12; nextMatrix.a14 = this.a14; nextMatrix.a21 = this.a21; nextMatrix.a22 = this.a22; nextMatrix.a24 = this.a24; nextMatrix.isDirty = true; } } package opengl.matrix2d; import java.nio.FloatBuffer; public class Matrix2dStack { private static final int MAXDEPDTH = 32; private final Matrix2d[] matrices = new Matrix2d[MAXDEPDTH]; private Matrix2d current; private int iCur = 0; private boolean isDirty = true; public Matrix2dStack() { for (int i = 0; i < MAXDEPDTH; i++) { matrices[i] = new Matrix2d(); } current = matrices[iCur]; } public final void pop() { current = matrices[--iCur]; isDirty = true; } public final void push() { final Matrix2d next = matrices[++iCur]; current.onPush(next); current = next; } public final void loadIdentity() { current.loadIdentity(); isDirty = true; } public final void rotateZ(final float angDeg) { current.rotateZ(angDeg); isDirty = true; } public final void scaleX(final float scale) { current.scaleX(scale); isDirty = true; } public final void scaleY(final float scale) { current.scaleY(scale); isDirty = true; } public final void scaleXY(final float sx, final float sy) { current.scaleXY(sx, sy); isDirty = true; } public final void translateXY(final float dx, final float dy) { current.translateXY(dx, dy); isDirty = true; } public final void translateX(final float dx) { current.translateX(dx); isDirty = true; } public final void translateY(final float dy) { current.translateY(dy); isDirty = true; } public final FloatBuffer getBuffer() { return current.getBuffer(); } public final FloatBuffer copyInto(final FloatBuffer fb) { return current.copyInto(fb); } public final boolean wasDirty() { final boolean wasDirty = isDirty; isDirty = false; return wasDirty; } } For the stack class the wasDirty method is there as a utility for the renderer. It is to make sure it doesnt load the same modelview matrix 2 times in a row with glloadMatrixF. The name "wasDirty" should probably be renamed to something like "loadInto" and take the gl interface as an input. Edited July 24, 2011 by =RvE=Yoda S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'
RvEYoda Posted July 25, 2011 Author Posted July 25, 2011 (edited) Ah crap. Forget everything I've ever written. Looks like I've been looking in the wrong place :P. I made some proper profiling and there are 2 things taking up 80% of the cpu time in gear: About half of that is doing the actual geometry rendering: gl.glVertexPointer(2, GL2.GL_FLOAT, 0, vertices); gl.glDrawElements(primitiveType, nVertices, GL2.GL_UNSIGNED_INT, indices); and the other half is calling the JOGL textrenderer: tr.draw3D(text, x, y, 0, scale); tr.flush(); If I comment out those 4 lines then execution time is cut by > 80%. Stupid stupid stupid Yoda..please do profiling properly next time from the start. Sending transformation matrices = super fast, cos/sin is only responsible for about 4-5% of the total time. In the process however I did write new cos/sin implementations that run a lot faster, using pre-generated tables of taylor polynomials, implementation below (Just too bad these dont do more than cut the execution time by 2% :P due to the above mentioned!): public final static float sinTaylorTable(float x) { x = x % TWOPI; final int base = blockSize * (int) (scaleF * (offsF + x)); final float x0 = sinData[base], d0 = sinData[base + 1], d1 = sinData[base + 2], d2 = sinData[base + 3], r = x - x0; return d0 + d1 * r + d2 * r * r / 2.0f; } public final static float cosTaylorTable(float x) { x = x % TWOPI; final int base = blockSize * (int) (scaleF * (offsF + x)); final float x0 = cosData[base], d0 = cosData[base + 1], d1 = cosData[base + 2], d2 = cosData[base + 3], r = x - x0; return d0 + d1 * r + d2 * r * r / 2.0f; } Edited July 25, 2011 by =RvE=Yoda S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'
RvEYoda Posted July 25, 2011 Author Posted July 25, 2011 Alright now using VBOs and checked some other stuff. Profiled again and the jogl TextRenderer now takes up about 70% of the entire cpu time spent during one OpenGL display iteration. Out of the remaining 30% rendering VBOs takes up about half and the rest is other minor stuff. So if performance is not good enough now well...Someone write a new text renderer for me ^^. S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'
Haggart Posted July 25, 2011 Posted July 25, 2011 Hey - if you need sometime again an Eagle-jockey for testing, contact me by ICQ/MSN - I've basic knowledge of java and debugging and know how to handle conflicting software ;-) There's no "Overkill". There's only "open fire!" and "time to reload". Specs: i7-980@4,2Ghz, 12GB RAM, 2x GTX480, 1x 8800GTS, X-Fi HD, Cougar, Warthog, dcs-F16-pedals
RvEYoda Posted July 25, 2011 Author Posted July 25, 2011 Hey - if you need sometime again an Eagle-jockey for testing, contact me by ICQ/MSN - I've basic knowledge of java and debugging and know how to handle conflicting software ;-) Cool. Pm me your MSN details and ill contact you S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'
Moa Posted July 26, 2011 Posted July 26, 2011 Yoda, are you caching the rendered text to a (transparent) BufferedImage? You shouldn't re-render the text if it hasn't changed (although I have a feeling whether I asked you this a year ago). Trade memory for speed. The other thing you could do is pre-render all alphanumeric characters to a texture and then use texture coordinates to select the letters. You won't get proper kerning (although machine interfaces are lousy for this anyway) but it is fast. ED seems to do this by loading characters as textures (eg for aircraft numbers etc).
RvEYoda Posted July 26, 2011 Author Posted July 26, 2011 (edited) Yoda, are you caching the rendered text to a (transparent) BufferedImage? You shouldn't re-render the text if it hasn't changed (although I have a feeling whether I asked you this a year ago). Trade memory for speed. The other thing you could do is pre-render all alphanumeric characters to a texture and then use texture coordinates to select the letters. You won't get proper kerning (although machine interfaces are lousy for this anyway) but it is fast. ED seems to do this by loading characters as textures (eg for aircraft numbers etc). I use the JOGL built in class TextRenderer. It does that stuff for me (keeps a cache as a set of dynamically changing preloaded textures of rendered strings) , but has serious overhead problems :P. Not efficiently written. I am trying to get some more answers about it in jogamp forums (see http://forum.jogamp.org/Which-JOGL-TextRenderer-should-I-use-tp3199861p3199861.html;cid=1311671711804-713). If you got some text rendering class for JOGL 2 that is fast, then I'd love to use it :). However it does feel good to know that at least my code is fast, and the limiting factor is JOGL and opengl itself (the two heaviest things being glDrawElements and textrendering) With text rendered I am getting about 2200-2500 fps, and if I remove my text (just rendering geometry by commenting out tr draw3d and flush calls) I get ~ 8000 fps Edited July 26, 2011 by =RvE=Yoda S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'
RvEYoda Posted July 28, 2011 Author Posted July 28, 2011 (edited) Approaching a point where gear has virtually all features of LEAVU(2). When I get home this weekend I'll try to get my eyes away from MLG Anaheim (Starcraft II) and take a first step towards release. The first thing I'll do is to create a public account to access the svn repository I'm using for GEAR. EDIT: Just realized that JRE/JDK/Java 7 was just released. Tested and works perfectly with gear. Too bad we can't use its new features, as most users probably will only have java6. Parts of java7 seem really useful like asyncronous io and switch/case on strings. Performance wise it seems to be 1:1 with java6. Also the new generics look interesting. Edited July 28, 2011 by =RvE=Yoda S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'
Moa Posted July 28, 2011 Posted July 28, 2011 svn access would be great. Once it is up I intend trying to control things via a webservice (via JAX-WS), eg. read aircraft state, and write some commands to it. Great stuff that it still works under Java 7. I hear Eclipse has a few issues (but then, it is generally less portable than Netbeans). Will also try experiment with text rendering using textures this weekend, and give you some source you can benchmark.
RvEYoda Posted July 28, 2011 Author Posted July 28, 2011 (edited) svn access would be great. Once it is up I intend trying to control things via a webservice (via JAX-WS), eg. read aircraft state, and write some commands to it. Great stuff that it still works under Java 7. I hear Eclipse has a few issues (but then, it is generally less portable than Netbeans). Will also try experiment with text rendering using textures this weekend, and give you some source you can benchmark. Well I think the current system is as fast as it gets. BUT if you can make a faster one then we will definitely want to use that :). I made some tests with text by rendering preloaded geometry (display lists and/or VBOs generated from AWT font coordinates) vs JOGLs preloaded texture based textrenderer, and...the textrenderer wins with a speed factor 2x-3x. To me that is quite convincing, and it also has nice AA etc...so I guess its performance is acceptable. The main point is, the text probably in all reason should be the heaviest part of my application. Rendering low poly sets of lines is simply much lighter than curved text or painting textures, at least that is my conclusion. Again I'm interested in seeing your results! About your web service, will you read/write to gear or to the lua exports? I have been thinking of getting data from xml instead of strings from the lua, but havent put my mind to that yet. Doing IO to gear via a web service I guess could also be fun :P. If you want to write such an interface then it would be great to incorporate it into the main project. I am already using simple xml for my gear presets: <?xml version="1.0" encoding="UTF-8"?> <root> <mainguisettings> <nofocusjni>true</nofocusjni> <volume>100</volume> <simclient> <host>localhost</host> <port>8079</port> <autoconnect>true</autoconnect> </simclient> <dlinkclient> <host>www.gigurra.se</host> <port>11009</port> <name>User</name> <password>red</password> <autoconnect>true</autoconnect> </dlinkclient> <!-- <dlinkhost> <port>11009</port> <password>red</password> <autoconnect>true</autoconnect> </dlinkhost> <dlinkhost> <port>11011</port> <password>blue</password> <autoconnect>true</autoconnect> </dlinkhost>--> </mainguisettings> <instruments> <instrument> <name>Mfd20</name> <sizex>400</sizex> <sizey>400</sizey> <posx>250</posx> <posy>200</posy> <windowframe>true</windowframe> <specifics> <bezelbuttons>true</bezelbuttons> <qp1>1</qp1> <qp2>2</qp2> <qp3>3</qp3> <curqp>1</curqp> <kbbindings> <key> <base>NUMBER1</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>NUMBER2</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>NUMBER3</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>NUMBER4</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>NUMBER5</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>NUMBER6</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>NUMBER7</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>NUMBER8</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>NUMBER9</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>NUMBER0</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>F1</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>F2</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>F3</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>F4</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>F5</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>F6</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>F7</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>F8</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>F9</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> <key> <base>F10</base> <modifier>LCTRL</modifier> <modifier>LSHFT</modifier> </key> </kbbindings> </specifics> </instrument> <instrument> <name>Mfd20</name> <sizex>400</sizex> <sizey>400</sizey> <posx>650</posx> <posy>200</posy> <windowframe>true</windowframe> <specifics> <bezelbuttons>false</bezelbuttons> <qp1>2</qp1> <qp2>4</qp2> <qp3>5</qp3> <curqp>0</curqp> <kbbindings> <key> <base>NUMBER1</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>NUMBER2</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>NUMBER3</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>NUMBER4</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>NUMBER5</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>NUMBER6</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>NUMBER7</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>NUMBER8</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>NUMBER9</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>NUMBER0</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>F1</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>F2</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>F3</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>F4</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>F5</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>F6</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>F7</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>F8</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>F9</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> <key> <base>F10</base> <modifier>RCTRL</modifier> <modifier>RSHFT</modifier> </key> </kbbindings> </specifics> </instrument> </instruments> </root> Considering putting java7 code into gear. I basically emulated the event based IO stuff which is using OS native stuff in java 7, by using standard Java 6 threads, but it's so much prettier in java7... example below: public static void main(String[] args) throws IOException { final AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open(); server.bind(new InetSocketAddress(12345)).accept(server, new CH()); } private static class CH implements CompletionHandler<AsynchronousSocketChannel, AsynchronousServerSocketChannel> { @Override public void completed(AsynchronousSocketChannel result, AsynchronousServerSocketChannel server) { System.err.println("NEW CLIENT, get next!"); server.accept(server, this); } @Override public void failed(Throwable exc, AsynchronousServerSocketChannel server) { try { System.err.println("Server bailing!"); server.close(); } catch (IOException ex) { Logger.getLogger(JavaAsync.class.getName()).log(Level.SEVERE, null, ex); } } } Edited July 28, 2011 by =RvE=Yoda S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'
Moa Posted July 29, 2011 Posted July 29, 2011 (edited) Besides reading aircraft state, I was hoping to be able to use Gear to access the Lua send commands, if they are available . That'd allow me to make use of my MacBook Pro (which Touch Buddy can't do) to control flaps, hook etc. For my purposes I don't need 60 fps update, so webservice access would be fine. I'm implementing a map control using igormk's fantastic TC-1 map (doesn't extend east to T'blisi unfortunately, but great for FC2), plus also has an alternative (partially working) Google Maps implementation (for off Black Sea/Georgia map areas, eg Nevada; yes, this would be handy for X-Plane, which I also like greatly). I'd like to read from Gear using a webservice rather than be bound directly to the Gear server instance (that way I can do expensive drawing operations on another machine that isn't running DCS - eg. my MacBook Pro). How are you parsing your XML, using JAXB? For my lottu tool I converted the Lua tables into XML and then parsed them with JAXB. JAXB can generated the needed classes from an XML schema, and parse an XML document of any complexity into those classes in a couple of lines of code. I also used JAXB for storing my configuration information (as you do). the nice thing is I can add properties to the class but don't have to change the parsing code at all (since JAXB cleverly/reflectively sorts out how to convert the XML to the class structure and vice versa). If you are curious about Lua to JAXB you can get example code from the lottu source (embedded into the executable JAR version of lottu), or get the [GPL v3] lottu Netbeans project from http://www.stallturn.com/wiki/en/lottu Caveat: I haven't got the associative map aspect of LUA tables working right, due to a limitation of JAXB. Have played around with it, but got distracted by something else so didn't finish. ps. System.err.println() is handy, but have a look at the java.util.logger.Logger class too. It supports changing verbosity through runtime log levels, and you can log simultaneously to a console and a file (for monitoring in real time as well as saving for post-fault forensics later). Incidentally I also wrote a Java parser that can read Tacview format exports in real time - but didn't release it due to the evil people would do with it (damn cheaters). Would be nice to get that moving map to have friendly units on it via Gear (a la 'Blue Force Tracker', or the ABRIS but for any aircraft). Edited July 29, 2011 by Moa
RvEYoda Posted July 29, 2011 Author Posted July 29, 2011 (edited) Besides reading aircraft state, I was hoping to be able to use Gear to access the Lua send commands, if they are available . That'd allow me to make use of my MacBook Pro (which Touch Buddy can't do) to control flaps, hook etc. For my purposes I don't need 60 fps update, so webservice access would be fine. I'm implementing a map control using igormk's fantastic TC-1 map (doesn't extend east to T'blisi unfortunately, but great for FC2), plus also has an alternative (partially working) Google Maps implementation (for off Black Sea/Georgia map areas, eg Nevada; yes, this would be handy for X-Plane, which I also like greatly). I'd like to read from Gear using a webservice rather than be bound directly to the Gear server instance (that way I can do expensive drawing operations on another machine that isn't running DCS - eg. my MacBook Pro). How are you parsing your XML, using JAXB? For my lottu tool I converted the Lua tables into XML and then parsed them with JAXB. JAXB can generated the needed classes from an XML schema, and parse an XML document of any complexity into those classes in a couple of lines of code. I also used JAXB for storing my configuration information (as you do). the nice thing is I can add properties to the class but don't have to change the parsing code at all (since JAXB cleverly/reflectively sorts out how to convert the XML to the class structure and vice versa). If you are curious about Lua to JAXB you can get example code from the lottu source (embedded into the executable JAR version of lottu), or get the [GPL v3] lottu Netbeans project from http://www.stallturn.com/wiki/en/lottu Caveat: I haven't got the associative map aspect of LUA tables working right, due to a limitation of JAXB. Have played around with it, but got distracted by something else so didn't finish. ps. System.err.println() is handy, but have a look at the java.util.logger.Logger class too. It supports changing verbosity through runtime log levels, and you can log simultaneously to a console and a file (for monitoring in real time as well as saving for post-fault forensics later). Incidentally I also wrote a Java parser that can read Tacview format exports in real time - but didn't release it due to the evil people would do with it (damn cheaters). Would be nice to get that moving map to have friendly units on it via Gear (a la 'Blue Force Tracker', or the ABRIS but for any aircraft). Moa u speak my language :D. Sending commands to lockon lua from gear is already on the drawing board and 90% already implemented. Moving map both inside gear and outside would be fantastic too, but how do you propose we handle the coordinates? Lockon has a flat world, x-plane has a round etc, we cant just use lat longs and the same map. In GEAR I actually don't expose a coordinate system at all. I instead use a replaceable data interface (just an abstract base class which u implement specific for your sim) that produces snapshots of Altitude msl, range, bearing, aspect. However instruments can ask for the interface to produce an implementation specific coordinate from a bearing/range/altitude/aspect and also the other way around, but all you get is an "Object" which u really dont know much about (Except it is useful for example for mark points and datalink messages so you can save certain points on the map, a BRALTASP snapshot is only valid if you stay in that point where you made it where as an implementation specific point is valid forever, cause it probably saves as lat/long/alt) It goes like this Lockon <-> lua <-> gear's fc2 data parser <-> gear's fc2togear data interface <-> gear instruments. The Data instruments in gear are completely independent of any fc2 stuff and this is something I want to keep it like, so if we want a moving map that might require knowledge of the underlying coordinate system, then we should need to implement some new abilities in the data interface. If you are on Msn I can show you arrg, but you might be working daytime also :helpsmilie: Here is the base class I'm using for the data interface, so you get an idea of what I mean: package gear.instrument.datainterface; import gear.GEAR; import java.io.Serializable; import java.util.UUID; import net.Parser; public abstract class DataInterface { private final GEAR gear; public abstract void inputDlinkData(final Object data); public abstract void inputSimData(final Object data); public abstract Parser getSimDataParser(); public abstract Serializable[] genDataForDlinkUpload(final UUID myUuid, final String myDlinkId); public SnapshotRdrCursor getSnapshotRdrCursor() { return new SnapshotRdrCursor(0, 0, 0, false, false); } public SnapshotA2ATarget[] getSnapshotTargets() { return new SnapshotA2ATarget[0]; } public SnapshotA2ADatalinkedWingman[] getSnapshotA2ADatalinkedWingmen() { return new SnapshotA2ADatalinkedWingman[0]; } public SnapshotNavPoint[] getSnapshotNavPoints() { return new SnapshotNavPoint[0]; } public SnapshotOwnPosition getSnapshotOwnPosition() { return new SnapshotOwnPosition(0, 0, false); } public SnapshotRadarConfig getSnapshotRadarConfig() { return new SnapshotRadarConfig(0, 0, 0, 0, 0, 0, 0, false, "", false); } public Serializable braltSnapshotToImplSpecCoords(final float altMsl_m, final float offNoseBearing_deg, final float fromAcRange_m) { return null; } public SnapshotPosition implSpecCoordsToBraltSnapshot(final Serializable backingData) { return null; } public DataInterface(final GEAR gear) { this.gear = gear; } public final UUID getMyUuid() { return gear.myUuid; } public final String getMyDlinkid() { return gear.getDlinkId(); } public void sendDlinkMsg(final Serializable... ss) { gear.transmitOverDlink(ss); } } The implemention for fc2 in gear looks something like this : package fc2; import fc2.nav.Fc2AircraftPosition; import fc2.nav.Fc2Position; import fc2.nav.Fc2WingMan; import fc2.state.Fc2DataContainer; import fc2.state.Fc2AcModes; import fc2.state.Fc2ContactMemory; import fc2.state.Fc2DlinkMemory; import fc2.state.Fc2Navpoints; import fc2.state.Fc2Payload; import fc2.state.Fc2RadarSettings; import fc2.state.Fc2SelfData; import fc2.state.Fc2TEWS; import gear.GEAR; import gear.instrument.datainterface.DataInterface; import gear.instrument.datainterface.SnapshotNavPoint; import gear.instrument.datainterface.SnapshotA2ADatalinkedWingman; import gear.instrument.datainterface.SnapshotOwnPosition; import gear.instrument.datainterface.SnapshotA2ATarget; import gear.instrument.datainterface.SnapshotRdrCursor; import gear.instrument.datainterface.SnapshotPosition; import gear.instrument.datainterface.SnapshotRadarConfig; import gear.instrument.globals.GlobalDlinkMessage; import gear.instrument.globals.Globals; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.UUID; import net.Parser; import net.PatternFinder; import static fc2.Fc2Utils.*; public final class Fc2DataManager extends DataInterface { // Dcs/fc format private final Fc2AcModes acModes; private final Fc2ContactMemory contactMemory; private final Fc2Navpoints navpoints; private final Fc2Payload payload; private final Fc2RadarSettings radarSettings; private final Fc2SelfData selfData; private final Fc2TEWS tews; private final Fc2DlinkMemory dlinkMemory; private final HashMap<String, Fc2DataContainer> simDataContainers = new HashMap<String, Fc2DataContainer>(10); // Gear format private SnapshotNavPoint[] snapshotNavPoints = new SnapshotNavPoint[0]; private SnapshotA2ATarget[] snapshotTargets = new SnapshotA2ATarget[0]; private SnapshotOwnPosition snapshotOwnPosition = new SnapshotOwnPosition(0, 0, false); private SnapshotRdrCursor snapshotHsdCursor = new SnapshotRdrCursor(0, 0, 0, true, false); private SnapshotA2ADatalinkedWingman[] snapshotDatalinkedWingmen = new SnapshotA2ADatalinkedWingman[0]; private SnapshotRadarConfig snapshotRadarConfig = new SnapshotRadarConfig(0, 0, 0, 0, 0, 0, 0, false, "LV", false); private boolean simSnapshotsUpToDate = false, dlinkSnapshotsUpToDate = false; @Override public final SnapshotOwnPosition getSnapshotOwnPosition() { ensureSnapshotsUpToDate(); return snapshotOwnPosition; } @Override public final SnapshotNavPoint[] getSnapshotNavPoints() { ensureSnapshotsUpToDate(); return snapshotNavPoints; } @Override public final SnapshotA2ATarget[] getSnapshotTargets() { ensureSnapshotsUpToDate(); return snapshotTargets; } @Override public final SnapshotA2ADatalinkedWingman[] getSnapshotA2ADatalinkedWingmen() { ensureSnapshotsUpToDate(); return snapshotDatalinkedWingmen; } @Override public final SnapshotRdrCursor getSnapshotRdrCursor() { ensureSnapshotsUpToDate(); return snapshotHsdCursor; } @Override public final SnapshotRadarConfig getSnapshotRadarConfig() { ensureSnapshotsUpToDate(); return snapshotRadarConfig; } @Override public Serializable braltSnapshotToImplSpecCoords(final float altMsl_m, final float offNoseBearing_deg, final float fromAcRange_m) { return snapshotToImplPos(selfData.getMyPos(), altMsl_m, offNoseBearing_deg, fromAcRange_m); } @Override public SnapshotPosition implSpecCoordsToBraltSnapshot(final Serializable backingData) { return (backingData instanceof Fc2Position) ? implPosToSnapshot(selfData.getMyPos(), (Fc2Position) backingData) : null; } @Override public final void inputSimData(final Object simData) { if (simData instanceof byte[]) { final String data = new String((byte[]) simData); final ArrayList<String> lines = new ArrayList<String>(data.length() / 7); int stringStart = 0; for (int i = 0; i < data.length(); i++) { if (data.charAt(i) == '\n' || i + 1 == data.length()) { lines.add(data.substring(stringStart, i)); stringStart = i + 1; } } int lineIndex = 0; boolean noUpdate = simSnapshotsUpToDate; while (lineIndex < lines.size()) { final Fc2DataContainer receiver = simDataContainers.get(lines.get(lineIndex)); if (receiver != null) { lineIndex = receiver.insertData(lines, lineIndex); noUpdate = false; } else { lineIndex++; } } simSnapshotsUpToDate = noUpdate; } } @Override public final Parser getSimDataParser() { return new Parser(new PatternFinder("!!dnacv02mJ8onvalPD893HNid8V9h6782sdu!!".getBytes())); } @Override public final void inputDlinkData(final Object data) { if (data instanceof Fc2WingMan) { dlinkMemory.insertWingman((Fc2WingMan) data); dlinkSnapshotsUpToDate = false; } else if (data instanceof GlobalDlinkMessage) { Globals.insertGlobalDlinkMessage((GlobalDlinkMessage) data); } } @Override public final Serializable[] genDataForDlinkUpload(final UUID myUuid, final String myDlinkId) { final Fc2AircraftPosition ap = selfData.getMyPos(); return new Serializable[]{new Fc2WingMan( myUuid, ap.typeCsv, ap.x_m, ap.z_m, ap.altMsl_m, ap.heading_rads, ap.worldID, ap.coalitionID, myDlinkId, contactMemory.getContacts(5))}; } private final void ensureSnapshotsUpToDate() { if (!simSnapshotsUpToDate) { snapshotNavPoints = implNavpointsToSnapshots(selfData, navpoints); snapshotOwnPosition = implOwnPosToSnapshot(selfData); snapshotTargets = implTargetsToSnapshots(selfData, contactMemory); snapshotHsdCursor = implRadCursorToSnapshot(selfData, radarSettings); snapshotRadarConfig = implRadarConfToSnapshot(radarSettings); simSnapshotsUpToDate = true; } if (!dlinkSnapshotsUpToDate) { snapshotDatalinkedWingmen = implDlinkedWingmenToSnapshots(selfData, dlinkMemory); dlinkSnapshotsUpToDate = true; } } @SuppressWarnings("CallToThreadStartDuringObjectConstruction") public Fc2DataManager(final GEAR gear) { super(gear); addImplSimDataContainer(simDataContainers, this.acModes = new Fc2AcModes()); addImplSimDataContainer(simDataContainers, this.contactMemory = new Fc2ContactMemory()); addImplSimDataContainer(simDataContainers, this.navpoints = new Fc2Navpoints()); addImplSimDataContainer(simDataContainers, this.payload = new Fc2Payload()); addImplSimDataContainer(simDataContainers, this.selfData = new Fc2SelfData()); addImplSimDataContainer(simDataContainers, this.radarSettings = new Fc2RadarSettings(this.selfData)); addImplSimDataContainer(simDataContainers, this.tews = new Fc2TEWS(gear.audioBank)); this.dlinkMemory = new Fc2DlinkMemory(); this.tews.start(); this.dlinkMemory.start(); } } It uses a few utility classes for coordinate manipulation. Edited July 29, 2011 by =RvE=Yoda S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'
RvEYoda Posted July 29, 2011 Author Posted July 29, 2011 (edited) Just had a look at JAXB, which I actually havent used :), but maybe should have. Ideally I would want to generate the xml format from a java class, and skip the schema, or go from java class -> xml schema -> xml (and be able to map both ways). BUT myself I actually didn't think/know about schemas etc, so I went and did the presets xml manually. but... we could always change it? :). However as you note in the xml presets there is a custom section called "specifics" where an instrument can put any text string they want, so that might be tricky to define in a schema? or maybe not :P. Here is how I do it right now (blunt brute force^^) : package gear.xml; import gear.GEAR; import gear.dlink.DlinkHubGui; import gear.instrument.Instrument; import gear.instrument.manager.InstrumentManager; import gear.instrument.manager.WindowSettings; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JOptionPane; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; public final class PresetLoader { private final GEAR gear; private final InstrumentManager im; public PresetLoader(final GEAR gear, final InstrumentManager im) { this.gear = gear; this.im = im; } public final void loadPreset(final File file) { try { final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file); doc.getDocumentElement().normalize(); final Element root = doc.getDocumentElement(); // do Main gui final Element mgs = (Element) root.getElementsByTagName("mainguisettings").item(0); final String wsexnofocusStr = mgs.getElementsByTagName("nofocusjni").item(0).getTextContent(), volumeStr = mgs.getElementsByTagName("volume").item(0).getTextContent(); // do sim client final Element simClient = (Element) mgs.getElementsByTagName("simclient").item(0); final String simClienthostStr = simClient.getElementsByTagName("host").item(0).getTextContent(), simClientportStr = simClient.getElementsByTagName("port").item(0).getTextContent(), simClientautoconnectStr = simClient.getElementsByTagName("autoconnect").item(0).getTextContent(); // do dlink client final Element dlinkClient = (Element) mgs.getElementsByTagName("dlinkclient").item(0); final String dlinkClienthostStr = dlinkClient.getElementsByTagName("host").item(0).getTextContent(), dlinkClientportStr = dlinkClient.getElementsByTagName("port").item(0).getTextContent(), dlinkClientnameStr = dlinkClient.getElementsByTagName("name").item(0).getTextContent(), dlinkClientpasswdStr = dlinkClient.getElementsByTagName("password").item(0).getTextContent(), dlinkClientautoconnectStr = dlinkClient.getElementsByTagName("autoconnect").item(0).getTextContent(); // Remove all previous instruments and disconnect clients before continuing gear.disconnectAll(); //im.killAllInstruments(); // load main gui settings gear.setWSEXNOACTIVATE(Boolean.valueOf(wsexnofocusStr)); gear.setVolume(Integer.valueOf(volumeStr)); // load simclient settings gear.setSimHost(simClienthostStr); gear.setSimPort(Integer.valueOf(simClientportStr)); if (Boolean.valueOf(simClientautoconnectStr)) { gear.onConnectSimButton(); } // load dlinkclient settings gear.setDlinkHost(dlinkClienthostStr); gear.setDlinkPort(Integer.valueOf(dlinkClientportStr)); gear.setDlinkId(dlinkClientnameStr); gear.setDlinkPassword(dlinkClientpasswdStr); if (Boolean.valueOf(dlinkClientautoconnectStr)) { gear.onConnectDlinkButton(); } gear.updateMainguiTextfields(); // do dlink host final NodeList dlinkHostList = mgs.getElementsByTagName("dlinkhost"); for (int i = 0; i < dlinkHostList.getLength(); i++) { final Element dlinkHost = (Element) dlinkHostList.item(i); final String dlinkHostportStr = dlinkHost.getElementsByTagName("port").item(0).getTextContent(), dlinkHostpasswdStr = dlinkHost.getElementsByTagName("password").item(0).getTextContent(), dlinkHostautoconnectStr = dlinkHost.getElementsByTagName("autoconnect").item(0).getTextContent(); // load server if (Boolean.valueOf(dlinkHostautoconnectStr)) { new DlinkHubGui(gear.getMainGuiPos(), Integer.valueOf(dlinkHostportStr), dlinkHostpasswdStr).setVisible(true); } } { // do instruments final Element instrBaseElem = (Element) root.getElementsByTagName("instruments").item(0); final NodeList instrumentNodes = instrBaseElem.getElementsByTagName("instrument"); for (int i = 0; i < instrumentNodes.getLength(); i++) { final Element base = (Element) instrumentNodes.item(i); final String nameStr = base.getElementsByTagName("name").item(0).getTextContent(), sizexStr = base.getElementsByTagName("sizex").item(0).getTextContent(), sizeyStr = base.getElementsByTagName("sizey").item(0).getTextContent(), posxStr = base.getElementsByTagName("posx").item(0).getTextContent(), posyStr = base.getElementsByTagName("posy").item(0).getTextContent(), wndFrameStr = base.getElementsByTagName("windowframe").item(0).getTextContent(); final Element instrSpecifics = (Element) base.getElementsByTagName("specifics").item(0); im.onRequestCreateNewInstrument(nameStr, new WindowSettings(Integer.valueOf(sizexStr), Integer.valueOf(sizeyStr), Integer.valueOf(posxStr), Integer.valueOf(posyStr), Boolean.valueOf(wndFrameStr)), instrSpecifics); } } } catch (Exception ex) { Logger.getLogger(PresetLoader.class.getName()).log(Level.SEVERE, null, ex); JOptionPane.showMessageDialog(null, "Failed to load preset from file: " + file.getName()); } } public final void savePreset(final File selectedFile) { if (!selectedFile.exists()) { try { selectedFile.createNewFile(); } catch (Exception e) { JOptionPane.showMessageDialog(null, e.getMessage()); return; } } if (!selectedFile.canWrite()) { JOptionPane.showMessageDialog(null, "Unable to open file " + selectedFile.getName() + " for writing"); return; } try { final BufferedWriter bw = new BufferedWriter(new FileWriter(selectedFile, false)); bw.write(createXmlPreset()); bw.close(); } catch (IOException ex) { Logger.getLogger(PresetLoader.class.getName()).log(Level.SEVERE, null, ex); } } private final String createXmlPreset() { final XmlBuilder xb = new XmlBuilder(); xb.addSection("root"); { xb.addSection("mainguisettings"); { xb.addEntry("nofocusjni", gear.getWSEXNOACTIVATE()); xb.addEntry("volume", gear.getVolume()); xb.addSection("simclient"); { xb.addEntry("host", gear.getSimHost()); xb.addEntry("port", gear.getSimPort()); xb.addEntry("autoconnect", gear.getSimClientAlive()); } xb.closeSection(); // close simclient xb.addSection("dlinkclient"); { xb.addEntry("host", gear.getDlinkHost()); xb.addEntry("port", gear.getDlinkPort()); xb.addEntry("name", gear.getDlinkId()); xb.addEntry("password", gear.getDlinkPassword()); xb.addEntry("autoconnect", gear.getDlinkClientAlive()); } xb.closeSection(); // close dlinkclient xb.addSection("instruments"); { for (final Instrument i : im.getActiveInstruments()) { xb.addSection("instrument"); xb.addString(i.getXml()); xb.closeSection(); } } xb.closeSection(); // close instruments } xb.closeSection(); // close mainguisettings } xb.closeSection(); // close root return xb.toString(); } } Update: I found out now there is a JDK tool called "schemagen" which simply creates an xml schema from a java class. However it doesn't seem like there is any built in netbeans support for this, so it needs to be run from the command line..hmm.. Maybe I should just make my own using java reflection at some point ;P Moa we must find a better way to communicate. This two-posts-per-day is tooo slow. What we've told each other in a week can be done in 20 minutes on any IM program. It doesn't matter if it's skype or msn or icq. Something similar is required where we dont have to connect to a specific service for our communication (an irc channel or kenai chat is not good enough, we have to connect to it manually, both, beforehand, if we did that with all our contacts at least I'd have a million windows open at all times). I believe GEAR would be 2x as competent if you joined in. Edited July 29, 2011 by =RvE=Yoda S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'
RvEYoda Posted July 30, 2011 Author Posted July 30, 2011 (edited) Ok for everyone that wants to inspect and/or contribute to the source, "Public" SVN account is up! (read-only) It includes everything you need, from fc2 exports to native jogl libs and java code. I recommend you use Netbeans IDE for both checking it out and trying it. 1. Install 32bit Java JDK with Neatbeans 2. Open Netbeans and checkout the SVN repository from: rep: https://www.gigurra.se/svn/GEAR/GEAR user: public password (blank): Edited July 30, 2011 by =RvE=Yoda S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'
Cali Posted August 2, 2011 Posted August 2, 2011 Sorry Yoda, I thought I was going to have time to help you out, but I don't. Just started classes again and haven't been able to fly much in the last week, looks like it may be like this for a bit. i7-4820k @ 3.7, Windows 7 64-bit, 16GB 1866mhz EVGA GTX 970 2GB, 256GB SSD, 500GB WD, TM Warthog, TM Cougar MFD's, Saitek Combat Pedals, TrackIR 5, G15 keyboard, 55" 4K LED
DocPL Posted August 6, 2011 Posted August 6, 2011 Hi Thank you Yoda for the effort you made for LEAVU and now GEAR. I use nine monitors setup (two PC) for playing sims (F-16 Falcon 4 OF, A-10C DCS, F15C FC2). I somewhat like to fly russian fighters. Is it possible to inegrate in new GEAR soft russian radar window and russian style TEWS ? Cheers
RvEYoda Posted August 6, 2011 Author Posted August 6, 2011 Hi Thank you Yoda for the effort you made for LEAVU and now GEAR. I use nine monitors setup (two PC) for playing sims (F-16 Falcon 4 OF, A-10C DCS, F15C FC2). I somewhat like to fly russian fighters. Is it possible to inegrate in new GEAR soft russian radar window and russian style TEWS ? Cheers If someone codes that instrument, sure. Though I myself have no intention (at least now) to do this, anyone willing is free to add such a capability/instrument to the gear software and we'll add it to the official release. S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'
RvEYoda Posted August 7, 2011 Author Posted August 7, 2011 Flew a 4ship today on 44th teamspeak and talked about some things. Didn't really find any bugs with the software, ran silky smooth and well. Though we did implement a new bandwidth control which allows you to set your maximum allowed datalink upload limit. The update rate of the datalink will then adapt to match this. After a bit of work (messing around with tcp sockets) we were able to get high fps datalinks working on pretty low bandwidths. The Only important thing is to have a dlink server capable :). S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'
Udat Posted August 9, 2011 Posted August 9, 2011 (edited) Did some testing yesterday, luckily at least GG was around to help :P. We've decided that there is at least one tricky decision to make before moving on. What kind of symbols should we use for what kind of contacts? :/ Right now I have my own symbols but GG prefers http://www.baesystems.com/ProductsServices/bae_prod_eis_mids_terminals.html (and the problem is that THAT small picture is basically all information we've got there), though I don't know how to represent all types of targets with that. Basically these need to be easily distinguishable and easily remembered/intuitively understood: * My scan contacts (1 type of symbol) * My designated contact (1 type of symbol) * My designated primary target (1 type of symbol) * Datalinked scan contacts (1 type of symbol) * Datalinked designated contacts (1 type of symbol), comes with id of wingman number or name * Datalinked designated primary target (1 type of symbol), comes with id of wingman number or name * All the above must have 1 friendly version and one non-friendly version. Perhaps 3 versions (F, N, E) So we need at least 12 types :P All help and suggestions on this is helpful How about using red triangles for enemy, blue squares for neutral, and green circles for friendly as a basis, just to make the friend/foe part absolutely crystal clear. Scan, designated and primary could be differntiated by using thin-walled red triangle, thick-walled red triangles and full red triangles for instance, or perhaps put a green box on top of the primary and have only one walled version. Same with the neutral and Friendly contacts. The challenge then would be to differentiate between datalinked contacts and your own. something non-intrusive, but unmistakable, like a blue box around the symbol, or a little green "D" at its bottom left? Edited August 9, 2011 by Udat Intel i7-950 @stock, Asus P6X58D-E, 3x4GB Corsair Vengeance, Asus GTX 580, Corsair 120GB SSD, Corsair HX 750W PSU [sIGPIC][/sIGPIC]
Presing Posted August 15, 2011 Posted August 15, 2011 ...The challenge then would be to differentiate between datalinked contacts and your own. something non-intrusive, but unmistakable, like a blue box around the symbol, or a little green "D" at its bottom left? D idea is very good I think. You could use D marker in the symbol (triangle or circle). You do not need neutrals because there is no neutrals in the DCS Serial, maybe they made neutrals some day. Rocket brigade who retired F-117
RvEYoda Posted August 17, 2011 Author Posted August 17, 2011 (edited) D idea is very good I think. You could use D marker in the symbol (triangle or circle). You do not need neutrals because there is no neutrals in the DCS Serial, maybe they made neutrals some day. Small extra symbols placed nearby have a few problems though... They clutter things up a bit more plus it becomes difficult to tell what is going on when two guys are on top of each other. In these cases I prefer different colors. In priority of what is most important should be (imho): IFF, Source, lock/search type I have been away for a while, and I'm still not home (in Moscow atm), but... I am moving in the direction of making F-16 mlu type symbology with certain additions on my mfd instrument (Basically 85% the same as leavu symbology). You are of course free to add whatever symbology you like on other instruments you make for gear :). Edited August 17, 2011 by =RvE=Yoda S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'
Recommended Posts