Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Monday, 5 November 2012

3D Math: Rotate to point

1. Problem description:

    We have :
              - 3d object that is (let's assume), centered on the Y axis
Cone was rotated to face the point (x1,y1,z1)



         - arbitrary point in space v1 with the coordinates (x1,y1,z1)

    We want :
        - obtain the rotation matrix or Quaternion that will rotate your object towards the arbitrary point (look at)
        - so, input parameter is v1 and output will be a 4x4 transformation matrix

    Optional :
        - other implementations to this issue will also take as input parameters a up vector (in this case is the OY axis) and a rotation center (i used (0,0,0))

2. Implementation :


         - we solve this by finding the axis-angle representation for the rotation
         - i see this as the most simplest way, as many frameworks will already have implementations for the all math required (Vector Normalization, Cross Product, Dot Product, Axis-Angle to Matrix conversion)
         - code example, using the Vector3, Matrix4 and Quaternion classes from LibGdx  :
vec.nor();  
float angle = (float) (180f / Math.PI * Math.acos(vec.dot(Yaxis)));

  vec.crs(Yaxis);

  if (vec.len() == 0) {
   vec.set(Zaxis);
  }
  quaterion.set(vec, angle);
  vec.crs(Yaxis);
  if (vec.len() == 0) {   vec.set(Zaxis);  }  quaterion.set(vec, angle);  transformMatrix.rotate(quaterion.conjugate());
             1. Normalize v1
             2  Find the angle between OY and v1 :
                        - calculate the dot product between the 2 vectors to get the cosine of the angle between them
                        - get the angle value in radians by applying arccosine
                        - convert to degrees if necessary
             3. Calculate cross product between the vectors, to obtain the rotation axis, the vector that is perpendicular on both OY and v1
             4. If the cross product is zero (vectors are parallel), we use OZ as rotation axis
             5. We now have a rotation axis and a rotation angle.
                 This can be used as input to create a transformation matrix or a Quaternion(indirect aproach).
                 If,  using something like the code above, make sure your roation matrix is set to identity
                 If, for some reason you need to do the math yourself, see Conversion_from_and_to_axis-angle

Saturday, 6 October 2012

Android NDK, simple step by step guide

NDK allows you to use native(C, C++) code for your android application and it's a delicate subject.

The book "Android NDK Beginner's Guide" by Sylvain Ratabouil is 425 pages long and it's just a "beginner's guide". I will try to make this as short as possible, and provide a quick step by step guide to a working NDK example.

What you need :
  - working Android environment. I will use Eclipse on Windows for this so it will be easier to have the same. Working means you already succeed with a Hello World example
 - Android NDK - check http://developer.android.com/tools/sdk/ndk/index.html. As a alternative in future developemnts you can also use CristaX's custom made NDK, which has some improvements but for this example the one from Google is enough
 - Cygwin - only for windows devices
 - for simplicity, NDK should just be unzipped to a directory and Cygwin installed via installer. No headaches with environment variables & stuff for now.  For this example, it should be enough.

The steps :
So, we will do the sum of two numbers, written in native code and used in the android project  :

1. Prepare your android project  : 
                 - you need a android project in Eclipse to begin with
                 - in the root directory(same level with "src"), create a new directory called "jni"
                 - in a package of your choosing(for me : com.blogspot.soiuz - replace all later occurrences with your package name) create the SimpleLib java class and add the code :
package com.blogspot.soiuz; 
public class SimpleLib {
 static {
 System.loadLibrary("sLib");
 }
  // Native  - sum of two numbers
 public static native long add(int a, int b);
}


                  - this is the minimum you need : loadLibrary with the name of the native library we will later create(in this case "sLib") and at least one function declaration to use\test(in this case, adding of two numbers).
                 - based on the code here we will automatically generate a header file, so this is important
                 - open Command Prompt, and navigate to the bin directory of your android project
                 - to create a header file, we will use javah from the JDK tools by calling :
                                                                      javah -jni com.blogspot.soiuz.SimpleLib
                 - if it says it cannot find the class, make sure you can navigate from the bin directory, to SimpleLib.java by going com\blogspot\soiuz\SimpleLib. EG: you might need to step into the directory classes and run javah from there.
                 - in the pointed directory you will have com_blogspot_soiuz_SimpleLib.h, This is the C header file that we need to implement next.
                 - move this file to the jni folder and refresh the folder in Eclipse
                 - if you look into the file, you will have the add function written in a wierd manner : JNIEXPORT jlong JNICALL Java_com_blogspot_soiuz_SimpleLib_add , this is standard jni signature

2. Implementing the C library :
                -  right-click on the jni folder and choose New→File. Save it as sLib.c
                -  add code to it :

#include "com_blogspot_soiuz_SimpleLib.h"
long add(int a, int b) {
 return a+b;
}
JNIEXPORT jlong JNICALL Java_com_blogspot_soiuz_sLib_add(JNIEnv *env, jclass obj, jint a, jint b) {
 return add(a, b);
}

            - so we : add the header, implement our method in C, copy the method declaration for the generated header file and the variable names and call the native function. Easy.

3. The Makefile :
              - we have some files and this makefile will tell how they will be used
              - so, again, New -->File and create Android.mk
              - add text to it :
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sLib
LOCAL_SRC_FILES := sLib.c
include $(BUILD_SHARED_LIBRARY)

            - no spaces empty lines, indentation.All text should start from begin of line
            - in the makefile we need to specify : Module library - sLib, files we want to build - sLib.c

4. Building all :
           - for this we need 2 tools : NDK , and if you want to do this on windows you also need Cygwin 
           - assuming both are installed and configured, open cygwin and execute the 2 next commands
           -  cd /cygdrive/d/workspace/AndroidNdk (navigates to android project root directory. All drives are mapped under cygdrive)                                       
           -  /cygdrive/d/install/android-ndk-r6b/ndk-build (form the Ndk installation directory, it will execute ndk-build)
           - if all was ok, it will show some text saying that libsLib.so was created in \libs\armeabi\.This is the needed library

5. Using, testing
          - SimpleLib.add(1,2); This is all you need to do
          - class SimpleLib is already created inside the android project and i suggest you make a class like that to act as a intermediary between java code and native library