tag:blogger.com,1999:blog-64583257124737103722024-03-13T10:06:01.851-07:00Software PioneeringSoftware Pioneering is a blog about and for the adventurous side of software development.Rickardhttp://www.blogger.com/profile/17954757065272982081noreply@blogger.comBlogger11125tag:blogger.com,1999:blog-6458325712473710372.post-83950099202677923182017-07-21T02:12:00.000-07:002017-07-21T02:19:03.566-07:00Solving OpenAI Gym's CartPole-v0 environmentThis is a cross-post of the write-up of my submission for <a href="https://gym.openai.com/envs/CartPole-v0" target="_blank">OpenAI's CartPole</a> problem (with some corrections and clarifications).<br />
<br />
<h4>
Introduction and background:</h4>
I'm a novice when it comes to
Reinforcement Learning but it's a subject I've become obsessed with
lately. I've taken a couple of courses and done some machine learning experiments before (more specifically, a supervised learned bot for <a href="https://www.codingame.com/multiplayer/bot-programming/coders-strike-back" target="_blank">Codingame's Coders Strike Back</a>), but on reinforcement learning, pretty much all of which I've read is
<a href="https://karpathy.github.io/2016/05/31/rl/" target="_blank">Andrej Karpathy’s Pong from pixels</a> (which is also how I found the AI
Gym, incidentally).<br />
<br />
I did not use any framework for the neural network, it is based on my own rudimentary architecture for supervised learning.<br />
<br />
As for environment, I used <a href="https://github.com/deeplearning4j/gym-java-client" target="_blank">deeplearning4j's gym-java-client</a> to be able to code in Java. I
should also mention I had some issues with crashes in the
simulator. This is why the evaluation is so short and probably why it
converges so early (it forced me to optimize so it would succeed before
crashing).<br />
You can see the evaluation and write-up here: <a href="https://gym.openai.com/evaluations/eval_Re3dPtpgQzuXAHLL83chtQ#reproducibility" target="_blank">neph1's evaluation</a><br />
<br />
<h4>
Brief:</h4>
I trained a logistic neural network with two hidden layers. Input nodes were the observations of the last 5 steps.<br />
I believe I'm using a gradient policy approach.<br />
<br />
<h4>
Neural Network Layout:</h4>
The size of the network had to be carefully designed. Deviating from the described network by only one or two nodes can cause severe degradation in performance. See “Alternatives and Red Herrings” for information about other designs I tried.<br />
20 input nodes (observations from 5 latest steps)<br />
26 hidden nodes in first layer<br />
14 hidden nodes in second layer<br />
2 output nodes<br />
All nodes are logistic. Layers are fully interconnected<br />
<br />
<h4>
Initial Weights:</h4>
All weights are randomly initialized to a value between -1.0 and 1.0.<br />
<br />
<h4>
Learning Rate:</h4>
Learning rate matters, but it is also quite forgiving. Anything between 0.15 and 0.7 works. But it seems keeping it around 0.25 is slightly better. This evaluation used 0.28 I believe.<br />
<br />
<h4>
Input:</h4>
The input each step is divided by the (observed) bounds of that range. The exception is value 2 and 4 where I found that blowing these up (dividing by 0.05) led to a significant performance in learning. I expect this is due to enforcing a low velocity. Those values are then also capped to between -5 and 5. I believe that by blowing up the values I do something that RL purists might not be OK with, since I essentially tell the algorithm which values to focus on. <br />
<br />
<h4>
Scoring:</h4>
I tried a number of different scoring methods.<br />
What worked best in the end was:<br />
Compare position of each observed input with the one from the previous.<br />
If better (closer to zero), set gradients to positive (1.0), otherwise negative (-1.0). I’ve tried more variable gradients, like using the score directly, but it didn’t work as well.<br />
<br />
<pre style="background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2wRadlvwx6qgHb1A_AtkNVq1ucBe4p3mIefPALO14-0IW1WheyAJeq2vqd62V_YlbfORaCHMa7DL154Epsc1EDHNDkcLkLxf58vbr7MNgRH5KzRMrHCTsk23cNxUsFuPQIDGBx0C4k7TC/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> float score = 0;
for (int i = 0; i &lt; 4; i++) {
float delta = (Math.abs(observation[i + 4]) - Math.abs(observation[i]));
score += delta;
}
if (score > 0) {
score = 1f;
} else {
score = -1f;
}
float[] scores = lastAction == 0 ? TEMP_SCORE_LEFT : TEMP_SCORE_RIGHT;
decisions.add(new float[][]{lastInput, scores});
updateScore(3, score);
} </code></pre>
<br />
<br />
Then also update the previous two inputs with a diminishing value in the updateScore method. The factor seems to be forgiving, 0.55 to 0.95 have been tried, where 0.8 seems to be a good level).<br />
<br />
<pre style="background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2wRadlvwx6qgHb1A_AtkNVq1ucBe4p3mIefPALO14-0IW1WheyAJeq2vqd62V_YlbfORaCHMa7DL154Epsc1EDHNDkcLkLxf58vbr7MNgRH5KzRMrHCTsk23cNxUsFuPQIDGBx0C4k7TC/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> private void updateScore(int turnsAgo, float scoreChange) {
int size = decisions.size();
int min = Math.min(size, turnsAgo);
for (int i = 0; i < min; i++) {
float[] scores = decisions.get(size - i - 1)[1];
// increase scores by scoreChange
scoreChange *= 0.8f;
}
} </code></pre>
<br />
<h4>
Training:</h4>
When it came to training and using the training data I tried two different models.<br />
1. Keep neural network between episodes. Train using only the data from the latest episode.<br />
2. Reinitialize network each episode (keep initial weights). Keep all training data and train on whole set (all episodes).<br />
In both cases the training data is shuffled before use and the back propagated.<br />
Apart from the obvious benefit of less total training time on model 1, model 2 also led to much better learning performance.<br />
<br />
<h4>
Soft Max:</h4>
For a long time I used Soft Max to determine the action. Once the network improved, it became obvious that a deterministic approach led to better outcome (just use whichever output is higher).<br />
<br />
<h4>
Debugging:</h4>
To observe performance I printed out the following information after each episode:<br />
Episode number<br />
Score for episode<br />
Average over all episodes so far<br />
Rolling average (this differed from between 10 and 100 episodes)<br />
Highest value so far (less interesting once reaching highest score was frequent. Still interesting to see when it reaches 200 the first time).<br />
Total reward<br />
<br />
<br />
<br />
<h4>
Alternatives and red herrings:</h4>
Possible to train with 6 time steps (but not at same level of performance)<br />
24 input nodes<br />
32 hidden nodes in first layer<br />
16 hidden nodes in second layer<br />
2 output nodes<br />
<br />
One scoring method I tried was to compare relative movement with the previous step. The idea was that even if the model made a good move, if the velocity in the opposite direction was too high, it wouldn't get noticed when just watching the position of the rod and cradle. So, by comparing delta v of the previous move, I thought it might be possible to spot those things. But either my theory was wrong, or I didn't manage to find good values for the scoring.<br />
<br />
Another thing I experimented with was comparing the current position(s) with that more than one step back. Again, I was not able to find any good way of factoring this information into the scoring. So instead I placed my bets on the network figuring this out for itself.<br />
<br />
At one point when I was thinking about how to improve the learning, I thought that more tranining examples would be a good thing (it's one of the fundamental rules in supervised learning, after all). Since the observation space is symmetric (or so I thought), I should be able to mirror all observations and scorings and get twice as many training examples. Awesome! Right? It turned out that wasn't the case. I was not able to use the mirrored data. I still think this would be worth exploring further.<br />
<br />
<br />
<h4>
Further improvements:</h4>
I still think mirroring the training examples should be possible. Doubling the training data should improve it significantly.<br />
<br />
Given the design of the network, it seems a Recurrent Neural Network (RNN) would be a good alternative. Anonymoushttp://www.blogger.com/profile/12037209318908497277noreply@blogger.com0tag:blogger.com,1999:blog-6458325712473710372.post-90109632372844529762016-12-03T02:01:00.002-08:002016-12-03T07:20:21.645-08:00Playing video in jMonkeyEngine 3 using vlcjA little while ago I made a <a href="https://github.com/neph1/jme3-vlcj" target="_blank">basic example</a> of how to play video on a texture in jMonkeyEngine 3. I used <a href="http://capricasoftware.co.uk/#/projects/vlcj/" target="_blank">vlcj</a> as the backing video player due to its relative ease of use and good tutorials. I'm making this companion post to describe the method (code) and how to set it up (config).<br />
<br />
This describes how to set it up in Netbeans on Windows (should be the same for other Maven projects).<br />
First, set up vlcj and build it: <br />
<ol>
<li>Download <a href="http://capricasoftware.co.uk/#/projects/vlcj/" target="_blank">vlcj</a>.</li>
<li>Set it up as a new project in Netbeans.</li>
<li>Change config to 'release'</li>
<li>Download suitable VLC.</li>
<li>Place libvlc and libvlccore in project root/win32-x86-64</li>
<li>Distribution ends up as a zip the project root/target folder.</li>
</ol>
Now you can set up a project that will use the vlcj build and point it to use the .jars in the target folder as libraries.<br />
<br />
I created a JmeRenderCallbackAdapter class based on this <a href="http://capricasoftware.co.uk/#/projects/vlcj/tutorial/direct-rendering" target="_blank">Direct Rendering tutorial</a>. The class takes a Texture2D as an input and will update its ImageBuffer on every onDisplay call.<br />
The method is very basic and there's an improvement to be made by using the native buffer directly.<br />
<br />
The TestVlcj class shows how to display the result.<br />
The setupView method creates a Quad and an Unshaded material to display the video on.<br />
It also creates a Texture2D (which is passed to JmeRenderCallbackAdapter) and an Image the same size as the application.<br />
The way BufferFormatCallback and DirectMediaPlayerComponent work are again taken directly from the Direct Rendering tutorial.<br />
TestVlcj takes a path to a video as input argument. The input argument can be overridden and mediaFile can be hard coded for testing.Anonymoushttp://www.blogger.com/profile/12037209318908497277noreply@blogger.com0tag:blogger.com,1999:blog-6458325712473710372.post-38392718566935515822015-07-13T06:21:00.000-07:002015-07-13T06:36:14.176-07:00Running jMonkeyEngine 3 on Android using AndroidHarnessFragment<div style="page-break-before: always;">
There's a new way of running
jMonkeyEngine 3 on Android, using fragments. Since I couldn't find a
description of how to do it or a use case, I thought I'd write down
how I did.</div>
The old (and still functional) used a class called <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">AndroidHarness</span></span></span>
that extended Activity and contained all the app specific information
in it. This post describes how to use the new <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">AndroidHarnessFragment</span></span></span>.<br />
<ul>
<li><div lang="en-US" style="margin-bottom: 0cm;">
<span>First
of all, <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">AndroidHarnessFragment</span></span></span>
contains a lot of app-specific settings. The most important of these
are <span style="color: green;"><span style="font-family: Times New Roman, serif;"><span style="font-size: x-small;"><b>appClass</b></span></span></span>,
which is a String containing the qualified name of the <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">Application</span></span></span>
to run. This and a lot of other fields are protected and it seems
the intended way of using the class is by extending it. This way you
can set all of them in the constructor of the new class, even if
there are other ways more aligned with Android conventions (such as
using a Bundle).</span></div>
</li>
<li><div lang="en-US" style="margin-bottom: 0cm;">
<span>Previously
the auto-generated <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">MainActivity</span></span></span>
class extended <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">AndroidHarness</span></span></span>.
Now it should just extend <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">Activity</span></span></span>.</span></div>
</li>
<li><div lang="en-US" style="margin-bottom: 0cm;">
<span>To
create the fragment, we can create a layout file for the activity:</span></div>
</li>
</ul>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><?xml
version="1.0" encoding="utf-8"?></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"</span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">android:orientation="vertical"</span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">android:layout_width="fill_parent"</span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">android:layout_height="fill_parent"</span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><fragment
android:name="com.mycompany.mygame.MyAndroidHarnessFragment"</span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">android:id="@+id/app_fragment"</span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">android:layout_width="match_parent"</span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">android:layout_height="match_parent"
/></span></span></div>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"></LinearLayout></span></span></div>
<ul>
<li><div lang="en-US" style="margin-bottom: 0cm;">
<span >Finally
we tell <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">MainActivity</span></span></span>
to use the layout file we just created.</span></div>
</li>
</ul>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">@Override</span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">protected
void onCreate(Bundle savedInstanceState) {</span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">super.onCreate(savedInstanceState);</span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">setContentView(R.layout.main);</span></span></div>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">}</span></span></div>
That's all that seems to be needed to run jMonkeyEngine inside a
fragment!Anonymoushttp://www.blogger.com/profile/12037209318908497277noreply@blogger.com0tag:blogger.com,1999:blog-6458325712473710372.post-4521855195719558082015-02-22T08:26:00.000-08:002015-07-13T06:36:47.794-07:00Google Cardboard support for jMonkeyEngine
<div style="margin-bottom: 0cm; page-break-before: always;">
I've just
<a href="https://github.com/neph1/jme-cardboard" target="_blank">commited support for Google Cardboard</a> in jMonkeyEngine 3. I plan on
doing a post with more details of the inner-workings, but in the meantime here's a
brief outline and how to use it.</div>
<div style="margin-bottom: 0cm;">
<br />
</div>
<div style="margin-bottom: 0cm;">
First of all, it's a completely
separate integration from the <a href="http://www.softwarepioneering.com/2015/01/virtual-reality-for-android-using.html" target="_blank">Android VR support project</a> I started.
This uses the <a href="https://www.google.com/get/cardboard/" target="_blank">Google Cardboard</a> API directly and in a way that didn't
fit with the architecture in that project.</div>
<div style="margin-bottom: 0cm;">
<br />
</div>
<div style="margin-bottom: 0cm;">
Why is it useful?</div>
<div style="margin-bottom: 0cm;">
<br />
</div>
<div style="margin-bottom: 0cm;">
It enables those who wish to use a
complete game development package to deploy their application as a
Google Cardboard app.</div>
<div style="margin-bottom: 0cm;">
<br />
</div>
<div style="margin-bottom: 0cm;">
So, how do I use it?</div>
<div style="margin-bottom: 0cm;">
<br />
</div>
Download the <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">jme-cardboard.jar</span></span></span>
from the repo and add it to your jMonkeyEngine project.
<br />
<ol>
<li><div style="margin-bottom: 0cm;">
Turn on Android deployment for
your project (<span style="color: green;"><span style="font-family: Times New Roman, serif;"><span style="font-size: x-small;"><b>Properties/Application/Android</b></span></span></span>)</div>
</li>
<li><div style="margin-bottom: 0cm;">
In the generated <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">MainActivity.java</span></span></span>
(<span style="color: green;"><span style="font-family: Times New Roman, serif;"><span style="font-size: x-small;"><b>Important
Files/Android Main Activity</b></span></span></span>) have it extend
<span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">CardboardHarness</span></span></span>
instead of <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">AndroidHarness</span></span></span>.
</div>
</li>
<li>Change the <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">appClass</span></span></span>
in the same to your project's application file.
<br />
</li>
</ol>
That should be it. For an example application, check out
<span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">CardboardStarTravel</span></span></span>
example in the test package.<br />
<br /><br />
<br />
If you wish to build the sources, it needs to have an android.jar
attached to the project.<br />
<br /><br />
<br />
Known issues.<br />
Drift with the accelerometer is pretty bad. Don't know if there is
anything to do about it on the application side.<br />
Movement is fairly jittery. Adding a filter for the accelerometer
might be desirable.<br />
<br />
<br />
Like I said, there will be more to come! <br />
Anonymoushttp://www.blogger.com/profile/12037209318908497277noreply@blogger.com0tag:blogger.com,1999:blog-6458325712473710372.post-82249210718777780762015-01-24T03:35:00.002-08:002015-10-03T01:56:04.700-07:00Designing a virtual reality HMD for smart phones<div style="margin-bottom: 0cm; page-break-before: always;">
Update: Design is now available on <a href="https://www.thingiverse.com/thing:1049924" target="_blank">Thingiverse.</a><br />
<br />
This is
supposed to be about software, I know. But without proper hardware
it's impossible to write any software. I realized when putting
together the <a href="http://www.softwarepioneering.com/2015/01/virtual-reality-for-android-using.html" target="_blank">Android VR library for jMonkeyEngine 3.0</a> that I had
nothing to test it on.</div>
<div style="margin-bottom: 0cm;">
The quickest solution to that problem
would be cutting out a <a href="https://www.google.com/get/cardboard/" target="_blank">Google Cardboard</a>. I'm not particularly fond of
cardboard, however and without it being laser-cut it would look
terrible. I have the benefit of owning a 3D-printer (Prusa i3) so I
thought I'd have a go at designing my own HMD inspired by the Google Cardboard schematics. They can only be used so far, though, since
they're meant to be cut and folded. Using a 3D-printer there are
benefits of being able to print complex geometry directly.</div>
<div style="margin-bottom: 0cm;">
I decided to build it in 3 steps, each
as simple as possible to avoid overhang problems. The first one would
be the cradle where the phone would rest.</div>
<div style="margin-bottom: 0cm;">
I based the measurements around my
Samsung Galaxy S4 and tried to design it to allow access to the
buttons on the side of the phone as well as the USB and audio. In
general, I tried to leave as much space as possible on the sides for
different phone types.</div>
<div style="margin-bottom: 0cm;">
Printing time is always an issue with
hobby printers, which is why I left the back side open. This and to
allow the battery some fresh air. There are holes in it as well (the
design anyway. The printer doesn't really make them). These are for
if at some point one would like to mimick the Oculus Rift DK2's
positional tracking by placing some LED's there.</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUQh-N1FYN7tP8lzfM7gUwH617oUDT9q8ebRnbOtX1W66fqLKFINRhIH7jZhAL3h4hbeQLuIVBdu5scZ06CF0WW_Lnx8rrqR1Zx3KoKvrmbCDwpbQOIIsW-sWXcSIQkzxLzEYQZPCbSAkx/s1600/part1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="218" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUQh-N1FYN7tP8lzfM7gUwH617oUDT9q8ebRnbOtX1W66fqLKFINRhIH7jZhAL3h4hbeQLuIVBdu5scZ06CF0WW_Lnx8rrqR1Zx3KoKvrmbCDwpbQOIIsW-sWXcSIQkzxLzEYQZPCbSAkx/s1600/part1.png" width="320" /></a></div>
<br />
<div style="margin-bottom: 0cm;">
Next, I went to the piece next to the
eyes as the middle part would just be about creating some distance
between the lenses and the screen (or so I thought). I happen to have
an Oculus Rift DK1 which isn't seeing much use now, so I decided to
butcher two of the eye cups for lenses. They are 36mm in diameter,
which should give some additional FOV compared to the 25mm
recommended for the Google Cardboard. Apart from making good fittings
for the lenses the biggest challenge with this piece was making it
fit well around the face.</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcvoWL2wKspyUEwB59MJ02w68KSsMKe7BY-B7PEEAZYANBIfr4pOcxDL70oP938-_iMJDov_4rW1lGXkDivhKeJtRg9KN9QNjEXxpVb6siDTP-cVq6aMkf9QDssDTnRPp0sd6UZIi246iY/s1600/part3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="273" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcvoWL2wKspyUEwB59MJ02w68KSsMKe7BY-B7PEEAZYANBIfr4pOcxDL70oP938-_iMJDov_4rW1lGXkDivhKeJtRg9KN9QNjEXxpVb6siDTP-cVq6aMkf9QDssDTnRPp0sd6UZIi246iY/s1600/part3.png" width="320" /></a></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
I think I actually spent most of the
time making the middle piece. Modelling a good cup for the nose was a
big challenge and I've scrapped several prints due to it not being
well printed. It's very spacious, and should suit most nose shape and
sizes. The other thing with it is that it's slightly wider at the
bottom than at the top. This is because I made the piece next to the
face slightly more narrow than the phone cradle. In the case I build
a Note-sized cradle, this would be even more pronounced.</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhovAt5b_IFPflt7niwywF8uRMrPE1faIz2rV7_VbVjIk-fHHGJgHcKmoSXLmBaikagx5IJibER2vjsqKeoZqyUMhYSk-O0jCvmMSeq4gjK18lO1cImfCu4Z_qCDGdKDLjs7rB9T557tYiU/s1600/part2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="273" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhovAt5b_IFPflt7niwywF8uRMrPE1faIz2rV7_VbVjIk-fHHGJgHcKmoSXLmBaikagx5IJibER2vjsqKeoZqyUMhYSk-O0jCvmMSeq4gjK18lO1cImfCu4Z_qCDGdKDLjs7rB9T557tYiU/s1600/part2.png" width="320" /></a></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
Below is the current state of the
prototype. It's working very well together with the Google Cardboard
demos. I can see some 5 mm outside of my S4 screen at the top and
bottom, so maybe an S5 would be perfect for these lenses.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8yn8AaTHThCmNqr5NzZSylSLzjVQ2gaAWZoM7LWLJgbXQ8VeojKWqRg2PjqSkxEcz4jYLEABle4uOIjeeMrKyeX3LUTEDqPH_Tc6sD34J7ac2k0698AYsSxRiNz8Mx9NaW74knzCxydL8/s1600/back_small.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8yn8AaTHThCmNqr5NzZSylSLzjVQ2gaAWZoM7LWLJgbXQ8VeojKWqRg2PjqSkxEcz4jYLEABle4uOIjeeMrKyeX3LUTEDqPH_Tc6sD34J7ac2k0698AYsSxRiNz8Mx9NaW74knzCxydL8/s1600/back_small.jpg" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1g5eYnyrLYueXueLswHtyTWs0apXBub027FPbQsCxrcwLm8Ojrm2pMNIc74_jBHvlT35335K84L8BLa3lUaYqDDFhda3tf6LDjnsvt6hkKZflMasBE-6geeCahr21mHpb5EhOoxkVmSbe/s1600/front_small.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1g5eYnyrLYueXueLswHtyTWs0apXBub027FPbQsCxrcwLm8Ojrm2pMNIc74_jBHvlT35335K84L8BLa3lUaYqDDFhda3tf6LDjnsvt6hkKZflMasBE-6geeCahr21mHpb5EhOoxkVmSbe/s1600/front_small.jpg" width="400" /></a></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
I want to have a fitting for a magnet on it as well but I seem to have lost the magnets I bought, for now.. </div>
<div style="margin-bottom: 0cm;">
I plan on sharing these as well as a
BOM for a complete HMD once I'm happy with the design. Stay tuned for
more.</div>
Anonymoushttp://www.blogger.com/profile/12037209318908497277noreply@blogger.com0tag:blogger.com,1999:blog-6458325712473710372.post-40738901043651989232015-01-02T01:52:00.003-08:002015-01-02T01:59:03.032-08:00Virtual Reality for Android using jMonkeyEngine<div style="margin-bottom: 0cm; page-break-before: always;">
Oculus Rift
may be leading the pack currently, but I'm sure there will be more
contenders for the virtual reality throne, shortly. So, while the
Oculus Rift plugin was a good start I think it is time to look into
what it would take to support more devices. The architecture
established for the Oculus Rift plugin is good enough and I decided
to see how much effort it would be to implement a basic virtual
reality API for Android. After all, the low-budget <a href="https://developers.google.com/cardboard/">Google
Cardboard</a> probably makes it the most accessible device of all.</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
You can find the repository for the
project here: <a href="https://github.com/neph1/jme-androidvr">https://github.com/neph1/jme-androidvr</a></div>
<h2 class="western">
Usage</h2>
<div style="margin-bottom: 0cm;">
It's implemented with ease of usage in
mind. An application wishing to use it needs to do two things.</div>
<ol>
<li><div style="margin-bottom: 0cm;">
Create a VRAppState instance and
supply a suitable HeadMountedDisplay (currently either a
DummyDisplay or AndroidDisplay).</div>
</li>
</ol>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">AndroidDisplay
display = new AndroidDisplay();</span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">VRAppState
vrAppState = new VRAppState(display);</span></span></div>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">stateManager.attach(vrAppState);</span></span></div>
<ol start="2">
<li><div style="margin-bottom: 0cm;">
For controls, get the
StereoCameraControl from the VRAppState and add it as a Control to a
Spatial. It will now follow the Spatial through the world.</div>
</li>
</ol>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">Node
observer = new Node("");</span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">observer.addControl(vrAppState.getCameraControl());</span></span></div>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">rootNode.attachChild(observer);</span></span></div>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">
</span></span></div>
<div style="margin-bottom: 0cm;">
See <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">AndroidVRTest</span></span></span>
for an example implementation.<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"> </span></span>
</div>
<h2 class="western">
Method</h2>
<div style="margin-bottom: 0cm;">
Like I stated in the beginning, it
follows closely what has already been implemented in the Oculus Rift
plugin but classes have been abstracted to allow for more diverse,
future, implementations.</div>
<div style="margin-bottom: 0cm;">
It revolves around class called
<span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">VRAppState</span></span></span>.
This class sets up two viewports and a <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">StereoCameraControl</span></span></span>
which handles the two different views.</div>
<div style="margin-bottom: 0cm;">
The <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">StereoCameraControl</span></span></span>
class gets its data (currently only rotation) from a class
implementing a <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">HeadMountedDisplay</span></span></span>
interface. In this example it's called <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">AndroidDisplay</span></span></span>.
The <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">AndroidDisplay</span></span></span>
class accesses the Android application and registers itself as a
<span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">SensorEventListener</span></span></span>
for the Accelerometer and Magnetometer. The default update delay is
way too slow, so it uses <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">SENSOR_DELAY_GAME</span></span></span>
instead.</div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">sensorManager
= (SensorManager)
JmeAndroidSystem.getActivity().getApplication().getSystemService(Activity.SENSOR_SERVICE);</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">accelerometer
= sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">magnetometer
= sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">sensorManager.registerListener(this,
accelerometer, SensorManager.SENSOR_DELAY_GAME);</span></span></div>
<div lang="en-US" style="margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">sensorManager.registerListener(this,
magnetometer, SensorManager.SENSOR_DELAY_GAME);</span></span></div>
<div style="margin-bottom: 0cm;">
Once sensor data is updated it's
received by the <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">onSensorChanged</span></span></span>
method. It updates our local values and confirms that data has been
received before getting the rotational data of the device in the form
of a <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">Matrix</span></span></span>.
This is stored in a temporary field and then orientation is
interpolated towards it. This was due to using the raw data was much
too jittery.</div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">public
void onSensorChanged(SensorEvent event) {</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"> if
(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"> gravity
= event.values;</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"> }
else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"> geomagnetic
= event.values;</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"> }</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"> if
(gravity != null && geomagnetic != null) {</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"> boolean
success = SensorManager.getRotationMatrix(R, I, gravity,
geomagnetic);</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"> if
(success) {</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"> SensorManager.getOrientation(R,
orientationVector);</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"> tempQuat.fromAngles(orientationVector[2],
-orientationVector[1], orientationVector[0]);</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"> orientation.slerp(tempQuat,
0.2f);</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"> }</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"> }</span></span></div>
<div lang="en-US" style="margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">}</span></span></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
It also needs to know about the
physical size of the screen. This is used by the distortion shader.
With some conversion it can be deducted from the Android applications
<span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">WindowManager</span></span></span>.
</div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">DisplayMetrics
displaymetrics = new DisplayMetrics();</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">JmeAndroidSystem.getActivity().getWindow().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);</span></span></div>
<div lang="en-US" style="margin-bottom: 0.09cm; margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">float
screenHeight = displaymetrics.heightPixels / displaymetrics.ydpi *
inchesToMeters;</span></span></div>
<div lang="en-US" style="margin-left: 0.64cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">float
screenWidth = displaymetrics.widthPixels / displaymetrics.xdpi *
inchesToMeters;</span></span></div>
<div style="margin-bottom: 0cm;">
This and other information is stored in
a class inspired by the Oculus Rift <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">HMDInfo</span></span></span>,
called <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">HeadMountedDisplayData</span></span></span>.
This contains data on the HMD itself, like distance between lenses,
distance from screen to lens, resolution, etc.</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
The shader is using the same principle
established early in the Oculus Rift plugin which itself was inspired
by an example implementation on the Oculus Developer web site (it
seems it has since been removed from the website. If anyone has a
link, please let me know). Each display has a post processing filter
and the necessary distortion correction is done in a fragment shader.
It begins with the class called <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">BarrelDistortionFilter</span></span></span>
which is instantiated in the <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">VRAppState</span></span></span>
class.</div>
<div style="margin-bottom: 0cm;">
The <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">BarrelDistortionFilter</span></span></span>
takes the information from the <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">HeadMountedDisplayData</span></span></span>
and creates a projection matrix for the <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">Camera</span></span></span>
associated with its <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">ViewPort</span></span></span>.
It also prepares some variables for the shader.</div>
<div style="margin-bottom: 0cm;">
The <span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;">scaleFactor</span></span></span>
value is an arbitrary number used to fit a specific screen. This most
likely needs a formula for different screen sizes.</div>
<h2 class="western">
References</h2>
<div style="margin-bottom: 0cm;">
jMonkeyEngine Oculus Rift plugin:</div>
<div style="margin-bottom: 0cm;">
<a href="https://code.google.com/p/jmonkeyengine-oculus-rift/">https://code.google.com/p/jmonkeyengine-oculus-rift/</a></div>
<div style="margin-bottom: 0cm;">
Sensors overview:</div>
<div style="margin-bottom: 0cm;">
<a href="http://developer.android.com/guide/topics/sensors/sensors_overview.html">http://developer.android.com/guide/topics/sensors/sensors_overview.html</a></div>
<div style="margin-bottom: 0cm;">
Registering sensors and reading
orientation data:</div>
<div style="margin-bottom: 0cm;">
<a href="http://www.codingforandroid.com/2011/01/using-orientation-sensors-simple.html">http://www.codingforandroid.com/2011/01/using-orientation-sensors-simple.html</a></div>
<div style="margin-bottom: 0cm;">
Google Cardboard:</div>
<div style="margin-bottom: 0cm;">
<a href="https://developers.google.com/cardboard/">https://developers.google.com/cardboard/</a></div>
Anonymoushttp://www.blogger.com/profile/12037209318908497277noreply@blogger.com0tag:blogger.com,1999:blog-6458325712473710372.post-77221095033843284922014-12-06T07:30:00.000-08:002014-12-06T07:30:48.976-08:00Free floating VR menu in jMonkeyEngine with Oculus Rift<h1 class="western">
</h1>
<div lang="en-US">
<span style="font-size: x-small;">The recommended
way of displaying GUI and menus in VR is to not have it static, tied
to the ”screen”. This despite the first thing you're being
greeted by when using the Oculus Rift is a big warning screen pasted
on your face.</span></div>
<div lang="en-US">
<span style="font-size: x-small;">The idea behind
a free-floating GUI is that it's more natural and adding to the
comfort of the user (which is a big thing in VR!). When it comes to
menus this also has the benefit of making the user able to do
selections without any other controller than the HMD itself.</span></div>
<div lang="en-US">
<span style="font-size: x-small;">In this tutorial
we'll create a menu that lets the user select menu items simply by
looking at them for a certain amount of time. I've chosen to write it similar to Packt's Cookbooks since it's something I'm
familiar with and it will hopefully make owners of the <a href="https://www.packtpub.com/game-development/jmonkeyengine-30-cookbook">jMonkeyEngine
3.0 Cookbook</a> feel right at home!</span><br />
<span style="font-size: x-small;"><br /></span></div>
<div lang="en-US">
<span style="font-size: x-small;">Disclaimer: The
API for the Oculus Rift plugin is in no way final and it might change
after this tutorial is written.</span></div>
<h2 class="western" style="font-style: normal;">
Preparation</h2>
<div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">We'll
need the Oculus Rift plugin for jMonkeyEngine. How to download and
set it up can be found here:
</span><a href="https://code.google.com/p/jmonkeyengine-oculus-rift/"><span style="color: blue;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">https://code.google.com/p/jmonkeyengine-oculus-rift/</span></span></span></span></a></span></div>
<div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">You can also find the full code for this tutorial in the "examples" folder.</span></span><br />
<span style="font-size: x-small;"><span style="font-style: normal;">This
tutorial won't explain how the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">OVRApplication</span></span></span></span><span style="font-style: normal;">
works, for this it's recommended to check out the project site's
wiki. The tutorial will be implemented in two classes. One
application class containing the basics and an </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">AppState</span></span></span></span><span style="font-style: normal;">
which will contain all the menu specific code.</span></span></div>
<h2 class="western">
<span style="font-style: normal;">Implementation</span></h2>
<span style="font-size: x-small;"><span style="font-style: normal;">We'll
start with the application class which is implemented in 5 steps.</span></span><br />
<ol>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">For
this example we start by creating a class that extends
</span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">OVRApplication</span></span></span></span><span style="font-style: normal;">.</span></span></div>
</li>
<li><div lang="en-US" style="margin-bottom: 0cm;">
<span style="font-size: x-small;"><span style="font-style: normal;">In
the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">simpleInit</span></span></span></span><span style="font-style: normal;">
method we start by removing the default GUI elements like this:</span></span></div>
</li>
</ol>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">setDisplayFps(false);</span></span></span></div>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">setDisplayStatView(false);</span></span></span></div>
<ol start="3">
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Next
we set up the GUI node for manual positioning and scale it somewhat.</span></span></div>
</li>
</ol>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">ovrAppState.getGuiNode().setPositioningMode(OculusGuiNode.POSITIONING_MODE.MANUAL);</span></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">ovrAppState.getGuiNode().setGuiDistance(0.5f);</span></span></span></div>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">ovrAppState.getGuiNode().setGuiScale(0.5f);</span></span></span></div>
<ol start="4">
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Like
in the example application for </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">OVRApplication</span></span></span></span><span style="font-style: normal;">
we create an observer node and assign the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">StereoCameraControl</span></span></span></span><span style="font-style: normal;">
to it.</span></span></div>
</li>
</ol>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Node
observer = new Node("Observer");</span></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">observer.setLocalTranslation(new
Vector3f(0.0f, 0.0f, 0.0f));</span></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">observer.addControl(ovrAppState.getCameraControl());</span></span></span></div>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">rootNode.attachChild(observer);</span></span></span></div>
<ol start="5">
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Now
we add two lines to the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">simpleUpdate</span></span></span></span><span style="font-style: normal;">
method to keep the GUI in place.</span></span></div>
</li>
</ol>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">guiNode.setLocalTranslation(cam.getLocation().add(0,
0, 0.5f));</span></span></span></div>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">guiNode.lookAt(cam.getLocation(),
Vector3f.UNIT_Y);</span></span></span></div>
<div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Apart
from revisiting to add the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">AppState</span></span></span></span><span style="font-style: normal;">,
that's it for the application class! The basics for the menu will be
done in the following 8 steps.</span></span></div>
<ol start="6">
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">We
start by creating a class called </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">MenuAppState</span></span></span></span><span style="font-style: normal;">
that extends </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">AbstractAppState</span></span></span></span><span style="font-style: normal;">.</span></span></div>
</li>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">We
define a number of colors we'll use to apply to the menu items to
indicate their status.</span></span></div>
</li>
</ol>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">private
static ColorRGBA DEFAULT_COLOR = ColorRGBA.DarkGray;</span></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">private
static ColorRGBA SELECT_COLOR = ColorRGBA.Gray;</span></span></span></div>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">private
static ColorRGBA ACTIVATE_COLOR = ColorRGBA.White;</span></span></span></div>
<ol start="8">
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Its
constructor should receive a width, height and the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">OculusGuiNode</span></span></span></span><span style="font-style: normal;">,
all which it stores in private fields.</span></span></div>
</li>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">We
also create and store a </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Vector2f</span></span></span></span><span style="font-style: normal;">
called </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">screenCenter</span></span></span></span><span style="font-style: normal;">
which should be initialized with </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">width
* 0.5f </span></span></span></span><span style="font-style: normal;">and</span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">
height * 0.5f;</span></span></span></span></span></div>
</li>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">In
the initialize method we start by creating and storing a </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Node</span></span></span></span><span style="font-style: normal;">
called </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">menuNode</span></span></span></span><span style="font-style: normal;">
and a </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Ray</span></span></span></span><span style="font-style: normal;">
called </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">sightRay</span></span></span></span><span style="font-style: normal;">.</span></span></div>
</li>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">We
set up a simple unshaded material to apply on the menu items and
give it the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">DEFAULT_COLOR</span></span></span></span><span style="font-style: normal;">.</span></span></div>
</li>
</ol>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Material
mat = new Material(app.getAssetManager(),
"Common/MatDefs/Misc/Unshaded.j3md");</span></span></span></div>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">mat.setColor("Color",
DEFAULT_COLOR);</span></span></span></div>
<ol start="12">
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Next
we create a number of menu items in the form of </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Quad's</span></span></span></span><span style="font-style: normal;">.
They're set up in a grid and each gets its own clone of the material
before being attached to the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">menuNode</span></span></span></span><span style="font-style: normal;">.</span></span></div>
</li>
</ol>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">for(int
x = -2; x < 2; x++){</span></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;"> for(int
y = -2; y < 2; y++){</span></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;"> Geometry
menuQuad = new Geometry("Test ", new Quad(width * 0.25f,
height * 0.25f));</span></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;"> menuQuad.setMaterial(mat.clone());</span></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;"> menuQuad.setLocalTranslation(x
* width * 0.25f, y * height * 0.25f, 0);</span></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;"> menuNode.attachChild(menuQuad);</span></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;"> }</span></span></span></div>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">}</span></span></span></div>
<ol start="13">
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Then
we attach the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">menuNode</span></span></span></span><span style="font-style: normal;">
to the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">guiNode</span></span></span></span><span style="font-style: normal;">.</span></span></div>
</li>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Now
we override the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">setEnabled</span></span></span></span><span style="font-style: normal;">
method and add some logic so that the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">menuNode</span></span></span></span><span style="font-style: normal;">
is added to the scenegraph when the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">AppState</span></span></span></span><span style="font-style: normal;">
is enabled and removed when it's disabled.</span></span></div>
</li>
</ol>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">if(enabled
&& !this.isEnabled()){</span></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;"> guiNode.attachChild(menuNode);</span></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">}
else if (!enabled && this.isEnabled()){</span></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;"> guiNode.detachChild(menuNode);</span></span></span></div>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">}</span></span></span></div>
<div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Now
we have a basic menu showing but no way of selecting anything. Adding
this functionality will consist of an additional 16 steps.</span></span></div>
<ol start="15">
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">First
of all we'll add another static field called </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">ACTIVATE_TIME</span></span></span></span><span style="font-style: normal;">
which is a </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">float</span></span></span></span><span style="font-style: normal;">
and set to </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">5f</span></span></span></span><span style="font-style: normal;">.</span></span></div>
</li>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">In
addition we need another </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">float</span></span></span></span><span style="font-style: normal;">
field called </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">timer</span></span></span></span><span style="font-style: normal;">,
a </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">CollisionResults</span></span></span></span><span style="font-style: normal;">
called </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">collisionResults</span></span></span></span><span style="font-style: normal;">
and a </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Geometry</span></span></span></span><span style="font-style: normal;">
called </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">selectedGeometry</span></span></span></span><span style="font-style: normal;">.</span></span></div>
</li>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">We
create a new method called selectItem which takes a </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Geometry</span></span></span></span><span style="font-style: normal;">
called </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">g</span></span></span></span><span style="font-style: normal;">
as input.</span></span></div>
</li>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Inside,
we set </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">selectedGeometry</span></span></span></span><span style="font-style: normal;">
to </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">g</span></span></span></span><span style="font-style: normal;">
and the color of its material to a clone of </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">SELECT_COLOR</span></span></span></span><span style="font-style: normal;">.</span></span></div>
</li>
</ol>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">selectedGeometry.getMaterial().setColor("Color",
SELECT_COLOR.clone());</span></span></span></div>
<ol start="19">
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Lastly
we set </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">timer</span></span></span></span><span style="font-style: normal;">
to 0.</span></span></div>
</li>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Now
we create another method called </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">unselectItem</span></span></span></span><span style="font-style: normal;">.</span></span></div>
</li>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Inside,
we check if </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">selectedGeometry</span></span></span></span><span style="font-style: normal;">
is not null and if so we set the color of its material to a clone of
</span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">DEFAULT_COLOR</span></span></span></span><span style="font-style: normal;">
before setting </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">selectedGeometry</span></span></span></span><span style="font-style: normal;">
to null.</span></span></div>
</li>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Next
we override the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">update</span></span></span></span><span style="font-style: normal;">
method and start by setting up the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Ray</span></span></span></span><span style="font-style: normal;">
we created in the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">initialize</span></span></span></span><span style="font-style: normal;">
method. It should originate from the camera.</span></span></div>
</li>
</ol>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">sightRay.setOrigin(app.getCamera().getWorldCoordinates(screenCenter,
0f));</span></span></span></div>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">sightRay.setDirection(app.getCamera().getDirection());</span></span></span></div>
<ol start="23">
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">We
do a collision check between the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Ray</span></span></span></span><span style="font-style: normal;">
and </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">menuNode</span></span></span></span><span style="font-style: normal;">
and see if any of the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Geometries</span></span></span></span><span style="font-style: normal;">
inside are being looked at. If any of them are we perform the
following piece of code to set the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Geometry</span></span></span></span><span style="font-style: normal;">
to the selected one.</span></span></div>
</li>
</ol>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Geometry
g = collisionResults.getClosestCollision().getGeometry();</span></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">if(g
!= selectedGeometry){</span></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;"> unselectItem();</span></span></span></div>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;"> selectItem(g);</span></span></span></div>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">}</span></span></span></div>
<ol start="24">
<li><div lang="en-US" style="margin-bottom: 0cm;">
<span style="font-size: x-small;"><span style="font-style: normal;">If
instead none is being looked at we call </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">unselectItem</span></span></span></span><span style="font-style: normal;">
to null a potentially </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">selectedGeometry</span></span></span></span><span style="font-style: normal;">.</span></span></div>
</li>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">After
performing this check we call the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">clear</span></span></span></span><span style="font-style: normal;">
method on </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">collisionResults</span></span></span></span><span style="font-style: normal;">.</span></span></div>
</li>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Before
doing the last bit in this method we create another (empty for now)
method called </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">activateItem</span></span></span></span><span style="font-style: normal;">.</span></span></div>
</li>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Continuing
in the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">update</span></span></span></span><span style="font-style: normal;">
method we check if </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">selectedGeometry</span></span></span></span><span style="font-style: normal;">
is not null.</span></span></div>
</li>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">If
it is assigned we increase </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">timer</span></span></span></span><span style="font-style: normal;">
by </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">tpf</span></span></span></span><span style="font-style: normal;">.</span></span></div>
</li>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Then
we perform the following piece of code to make the color brighter of
the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">selectedGeometry</span></span></span></span><span style="font-style: normal;">.</span></span></div>
</li>
</ol>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">float
interpolateValue = timer / ACTIVATE_TIME;</span></span></span></div>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">((ColorRGBA)selectedGeometry.getMaterial().getParam("Color").getValue()).interpolateLocal(SELECT_COLOR,
ACTIVATE_COLOR, interpolateValue);</span></span></span></div>
<ol start="30">
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">Lastly,
we check if </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">timer</span></span></span></span><span style="font-style: normal;">
is greater than </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">ACTIVATE_TIME</span></span></span></span><span style="font-style: normal;">
in which case we call the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">activateItem</span></span></span></span><span style="font-style: normal;">
method.</span></span></div>
</li>
<li><div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">The
final thing we need to do is to return to the application class and
create an instance of the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">MenuAppState</span></span></span></span><span style="font-style: normal;">
class.</span></span></div>
</li>
</ol>
<div lang="en-US" style="margin-bottom: 0cm; margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">MenuAppState
menuAppState = new MenuAppState(settings.getWidth(),
settings.getHeight(), (OculusGuiNode) guiNode);</span></span></span></div>
<div lang="en-US" style="margin-left: 1.91cm;">
<span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">stateManager.attach(menuAppState);</span></span></span></div>
<h2 class="western">
<span style="font-style: normal;">Explanation</span></h2>
<div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">In
the beginning of the application class, we telling the
</span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">OculusGuiNode</span></span></span></span><span style="font-style: normal;">
that we'll manage the positioning of the GUI ourselves. AUTO mode
will otherwise always place it in front of the camera and rotate with
it. We still want it to be in front of the camera which is why we
manually place it there. The difference is that the cameras rotation
won't be propagated to the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">guiNode's</span></span></span></span><span style="font-style: normal;">
translation. We also want the GUI to always face the camera even if
it's not strictly necessary for this example.</span></span></div>
<div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">In
the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">MenuAppState</span></span></span></span><span style="font-style: normal;">
we create a bunch of placeholder menu items in the form of </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Quads</span></span></span></span><span style="font-style: normal;">
which we align in a grid. In this example we attach and detach the
</span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">menuNode</span></span></span></span><span style="font-style: normal;">
via the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">setEnabled</span></span></span></span><span style="font-style: normal;">
method but depending on the rest of the application it might be
neater to do it using the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">stateAttached</span></span></span></span><span style="font-style: normal;">
and </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">stateDetached</span></span></span></span><span style="font-style: normal;">
methods.</span></span></div>
<div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">In
the update method we use raycasting originating from the camera to
detect if any of the menu items is in the center of the screen. When
this occurs we change the color of the item to indicate this to the
user and also begin a counter. We also start interpolating the color
of the selected item to indicate that something is happening. When
the timer exceeds 5 seconds it triggers an activation of the item.
It's not as quick as if one would have used a mouse but controlling
methods are different for VR and this enables the user to navigate
menus without having an additional controller.</span></span></div>
<div lang="en-US">
<span style="font-size: x-small;"><span style="font-style: normal;">The
one thing the example leaves out is what to do when an item is
selected. Since the example is using instances of </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Geometry</span></span></span></span><span style="font-style: normal;">
there's not much to do. A simple approach would be to create a
</span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">MenuItem</span></span></span></span><span style="font-style: normal;">
class that extends </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Geometry</span></span></span></span><span style="font-style: normal;">
or even better; add a custom </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Control</span></span></span></span><span style="font-style: normal;">
to the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">Geometry</span></span></span></span><span style="font-style: normal;">
which is called through the </span><span style="color: #747959;"><span style="font-family: Lucida Console, monospace;"><span style="font-size: x-small;"><span style="font-style: normal;">activateItem</span></span></span></span><span style="font-style: normal;">
method.</span></span></div>
Anonymoushttp://www.blogger.com/profile/12037209318908497277noreply@blogger.com0tag:blogger.com,1999:blog-6458325712473710372.post-26470755977688660912013-05-09T01:36:00.001-07:002013-05-09T05:11:47.087-07:00Java C++ wrapper for Oculus RiftI've wanted a VR helmet ever since i tried one for the first time in the early 90s. Looks like we're finally getting somewhere close to a commercial variant! Even if we don't, I'll be happy with the devkit I've ordered.Now, I'm a java developer, and thus I'm not too comfortable developing with the C++ SDK. Given that I have plenty of time before it arrives, I decided to make a wrapper, so I could continue to use jMonkeyEngine, which I'm more proficient with.<br />
<br />
The wrapper itself is not dependent on jME in any way. To build the C++ part, i recommend following the "Minimal Oculus Application" tutorial in the <a href="http://developer.oculusvr.com/" target="_blank">developer section of the Oculus web site</a>.<br />
<br />
Let's start with the java side.<br />
<br />
HMDInfo.java<br />
This is pretty much a direct mapping of the HMD(Head Mounted Display) data, straight from the C++ code, hence the naming convention is not 100% java.<br />
<br />
<br />
<pre style="background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2wRadlvwx6qgHb1A_AtkNVq1ucBe4p3mIefPALO14-0IW1WheyAJeq2vqd62V_YlbfORaCHMa7DL154Epsc1EDHNDkcLkLxf58vbr7MNgRH5KzRMrHCTsk23cNxUsFuPQIDGBx0C4k7TC/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> package oculusvr.input;
public class HMDInfo {
protected int HResolution;
protected int VResolution;
protected float HScreenSize;
protected float VScreenSize;
protected float VScreenCenter;
protected float EyeToScreenDistance;
protected float LensSeparationDistance;
protected float InterpupillaryDistance;
protected float[] DistortionK = new float[4];
protected int DesktopX;
protected int DesktopY;
protected String DisplayDeviceName = "";
protected long DisplayId = 0;
public int getHResolution() {
return HResolution;
}
public void setHResolution(int HResolution) {
this.HResolution = HResolution;
}
public int getVResolution() {
return VResolution;
}
public void setVResolution(int VResolution) {
this.VResolution = VResolution;
}
public float getHScreenSize() {
return HScreenSize;
}
public void setHScreenSize(float HScreenSize) {
this.HScreenSize = HScreenSize;
}
public float getVScreenCenter() {
return VScreenCenter;
}
public void setVScreenCenter(float VScreenCenter) {
this.VScreenCenter = VScreenCenter;
}
public float getEyeToScreenDistance() {
return EyeToScreenDistance;
}
public void setEyeToScreenDistance(float EyeToScreenDistance) {
this.EyeToScreenDistance = EyeToScreenDistance;
}
public float getLensSeperationDistance() {
return LensSeparationDistance;
}
public void setLensSeperationDistance(float LensSeperationDistance) {
this.LensSeparationDistance = LensSeperationDistance;
}
public float getInterpupillaryDistance() {
return InterpupillaryDistance;
}
public void setInterpupillaryDistance(float InterpupillaryDistance) {
this.InterpupillaryDistance = InterpupillaryDistance;
}
public float[] getDistortionK() {
return DistortionK;
}
public void setDistortionK(float[] DistortionK) {
this.DistortionK = DistortionK;
}
public int getDesktopX() {
return DesktopX;
}
public void setDesktopX(int DesktopX) {
this.DesktopX = DesktopX;
}
public int getDesktopY() {
return DesktopY;
}
public void setDesktopY(int DesktopY) {
this.DesktopY = DesktopY;
}
public String getDisplayDeviceName() {
return DisplayDeviceName;
}
public void setDisplayDeviceName(String DisplayDeviceName) {
this.DisplayDeviceName = DisplayDeviceName;
}
public long getDisplayId() {
return DisplayId;
}
public void setDisplayId(long DisplayId) {
this.DisplayId = DisplayId;
}
@Override
public String toString() {
return "HMDInfo [HResolution = " + HResolution +
", VResolution = " + VResolution +
", HScreenSize = " + HScreenSize +
", VScreenSize = " + VScreenSize +
", VScreenCenter = " + VScreenCenter +
", EyeToScreenDistance = " + EyeToScreenDistance +
", LensSeperationDistance = " + LensSeparationDistance +
", InterpupillaryDistance = " + InterpupillaryDistance +
", DistortionK = [" + DistortionK[0] + ", " + DistortionK[1] + ", " + DistortionK[2] + ", " + DistortionK[3] + "] " +
", DesktopX = " + DesktopX +
", DesktopY = " + DesktopY +
", DisplayDeviceName = " + DisplayDeviceName +
", DisplayId = " + DisplayId + "]";
}
} </code></pre>
<br />
OculusRift.java<br />
The wrapper on the java side. Should be pretty self-explanatory with initialization and getter methods. One note, due to the overhead involved in calling native methods, I decided to grab all the rotation and acceleration data in one go (update()).<br />
Please note that you might need to change the lib names depending on how you name your C++ project.<br />
<br />
<pre style="background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2wRadlvwx6qgHb1A_AtkNVq1ucBe4p3mIefPALO14-0IW1WheyAJeq2vqd62V_YlbfORaCHMa7DL154Epsc1EDHNDkcLkLxf58vbr7MNgRH5KzRMrHCTsk23cNxUsFuPQIDGBx0C4k7TC/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> /*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package oculusvr.input;
/**
*
* @author Rickard
*/
public class OculusRift {
static {
if(System.getProperty("sun.arch.data.model").equals("32")){
System.loadLibrary("OculusLib");
} else if (System.getProperty("sun.arch.data.model").equals("64")){
System.loadLibrary("OculusLib64");
}
}
public native boolean initialize();
/**
*
* @return array of [roll, pitch, yaw, acc x, acc y, acc z]
*/
public native float[] update();
// HMDInfo
public native int getHResolution();
public native int getVResolution();
public native float getHScreenSize();
public native float getVScreenSize();
public native float getVScreenCenter();
public native float getEyeToScreenDistance();
public native float getLensSeparationDistance();
public native float getInterpupillaryDistance();
public native float[] getDistortionK();
public native int getDesktopX();
public native int getDesktopY();
public native String getDisplayDeviceName();
public native long getDisplayId();
public native void destroy();
}
</code></pre>
<br />
<br />
<br />
<br />
That's all the java that's needed. To the C++ code!<br />
<br />
OculusRift.h<br />
The much needed header file. Generated with javah:<br />
<br />
<pre style="background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2wRadlvwx6qgHb1A_AtkNVq1ucBe4p3mIefPALO14-0IW1WheyAJeq2vqd62V_YlbfORaCHMa7DL154Epsc1EDHNDkcLkLxf58vbr7MNgRH5KzRMrHCTsk23cNxUsFuPQIDGBx0C4k7TC/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> /* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class oculusvr_input_OculusRift */
#ifndef _Included_oculusvr_input_OculusRift
#define _Included_oculusvr_input_OculusRift
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: oculusvr_input_OculusRift
* Method: initialize
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_oculusvr_input_OculusRift_initialize
(JNIEnv *, jobject);
/*
* Class: oculusvr_input_OculusRift
* Method: update
* Signature: ()[F
*/
JNIEXPORT jfloatArray JNICALL Java_oculusvr_input_OculusRift_update
(JNIEnv *, jobject);
/*
* Class: oculusvr_input_OculusRift
* Method: getHResolution
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_oculusvr_input_OculusRift_getHResolution
(JNIEnv *, jobject);
/*
* Class: oculusvr_input_OculusRift
* Method: getVResolution
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_oculusvr_input_OculusRift_getVResolution
(JNIEnv *, jobject);
/*
* Class: oculusvr_input_OculusRift
* Method: getHScreenSize
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_oculusvr_input_OculusRift_getHScreenSize
(JNIEnv *, jobject);
/*
* Class: oculusvr_input_OculusRift
* Method: getVScreenSize
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_oculusvr_input_OculusRift_getVScreenSize
(JNIEnv *, jobject);
/*
* Class: oculusvr_input_OculusRift
* Method: getVScreenCenter
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_oculusvr_input_OculusRift_getVScreenCenter
(JNIEnv *, jobject);
/*
* Class: oculusvr_input_OculusRift
* Method: getEyeToScreenDistance
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_oculusvr_input_OculusRift_getEyeToScreenDistance
(JNIEnv *, jobject);
/*
* Class: oculusvr_input_OculusRift
* Method: getLensSeparationDistance
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_oculusvr_input_OculusRift_getLensSeparationDistance
(JNIEnv *, jobject);
/*
* Class: oculusvr_input_OculusRift
* Method: getInterpupillaryDistance
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_oculusvr_input_OculusRift_getInterpupillaryDistance
(JNIEnv *, jobject);
/*
* Class: oculusvr_input_OculusRift
* Method: getDistortionK
* Signature: ()[F
*/
JNIEXPORT jfloatArray JNICALL Java_oculusvr_input_OculusRift_getDistortionK
(JNIEnv *, jobject);
/*
* Class: oculusvr_input_OculusRift
* Method: getDesktopX
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_oculusvr_input_OculusRift_getDesktopX
(JNIEnv *, jobject);
/*
* Class: oculusvr_input_OculusRift
* Method: getDesktopY
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_oculusvr_input_OculusRift_getDesktopY
(JNIEnv *, jobject);
/*
* Class: oculusvr_input_OculusRift
* Method: getDisplayDeviceName
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_oculusvr_input_OculusRift_getDisplayDeviceName
(JNIEnv *, jobject);
/*
* Class: oculusvr_input_OculusRift
* Method: getDisplayId
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_oculusvr_input_OculusRift_getDisplayId
(JNIEnv *, jobject);
/*
* Class: oculusvr_input_OculusRift
* Method: destroy
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_oculusvr_input_OculusRift_destroy
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
</code></pre>
<br />
OculusRift.cpp.<br />
This is pretty much an adaptation of the "Minimal oculus application" found on the oculus site.<br />
<br />
<pre style="background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2wRadlvwx6qgHb1A_AtkNVq1ucBe4p3mIefPALO14-0IW1WheyAJeq2vqd62V_YlbfORaCHMa7DL154Epsc1EDHNDkcLkLxf58vbr7MNgRH5KzRMrHCTsk23cNxUsFuPQIDGBx0C4k7TC/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> #include <jni.h>
#include <iostream>
#include <stdio.h>
#include "OVR.h"
#include "OculusRift.h"
using namespace OVR;
using namespace std;
Ptr<DeviceManager> pManager;
Ptr<HMDDevice> pHMD;
Ptr<SensorDevice> pSensor;
SensorFusion FusionResult;
HMDInfo Info;
bool InfoLoaded;
//#define STD_GRAV 9.81 // What SHOULD work with Rift, but off by 1000
#define STD_GRAV 0.00981 // This gives nice 1.00G on Z with Rift face down !!!
JNIEXPORT jboolean JNICALL Java_oculusvr_input_OculusRift_initialize
(JNIEnv *env, jobject thisObj) {
printf("Initializing Rift...\n");
System::Init();
bool initialized = false;
pManager = *DeviceManager::Create();
pHMD = *pManager->EnumerateDevices<HMDDevice>().CreateDevice();
if (pHMD){
printf("pHMD created\n");
InfoLoaded = pHMD->GetDeviceInfo(&Info);
pSensor = *pHMD->GetSensor();
}
else{
pSensor = *pManager->EnumerateDevices<SensorDevice>().CreateDevice();
}
if (pSensor)
{
printf("Attaching sensor\n");
FusionResult.AttachToSensor(pSensor);
initialized = true;
}
return initialized;
}
JNIEXPORT void JNICALL Java_oculusvr_input_OculusRift_destroyDevice
(JNIEnv *env, jobject thisObj) {
pSensor.Clear();
pHMD.Clear();
pManager.Clear();
System::Destroy();
return;
}
JNIEXPORT jfloatArray JNICALL Java_oculusvr_input_OculusRift_update
(JNIEnv *env, jobject thisObj) {
jfloat data[6];
Vector3f acc=FusionResult.GetAcceleration();
// yaw, pitch, roll
FusionResult.GetOrientation().GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&data[2], &data[1], &data[0]);
data[3] = acc.x / STD_GRAV;
data[4] = acc.y / STD_GRAV;
data[5] = acc.z / STD_GRAV;
jfloatArray result;
result = env->NewFloatArray(6);
if (result == NULL) {
return NULL; /* out of memory error thrown */
}
env->SetFloatArrayRegion(result, 0, 6, data);
return result;
}
JNIEXPORT jint JNICALL Java_oculusvr_input_OculusRift_getHResolution
(JNIEnv *env, jobject thisObj) {
return Info.HResolution;
}
JNIEXPORT jint JNICALL Java_oculusvr_input_OculusRift_getVResolution
(JNIEnv *env, jobject thisObj) {
return Info.VResolution;
}
JNIEXPORT jfloat JNICALL Java_oculusvr_input_OculusRift_getHScreenSize
(JNIEnv *env, jobject thisObj) {
return Info.HScreenSize;
}
JNIEXPORT jfloat JNICALL Java_oculusvr_input_OculusRift_getVScreenSize
(JNIEnv *env, jobject thisObj) {
return Info.VScreenSize;
}
JNIEXPORT jfloat JNICALL Java_oculusvr_input_OculusRift_getVScreenCenter
(JNIEnv *env, jobject thisObj) {
return Info.VScreenCenter;
}
JNIEXPORT jfloat JNICALL Java_oculusvr_input_OculusRift_getEyeToScreenDistance
(JNIEnv *env, jobject thisObj) {
return Info.EyeToScreenDistance;
}
JNIEXPORT jfloat JNICALL Java_oculusvr_input_OculusRift_getLensSeparationDistance
(JNIEnv *env, jobject thisObj) {
return Info.LensSeparationDistance;
}
JNIEXPORT jfloat JNICALL Java_oculusvr_input_OculusRift_getInterpupillaryDistance
(JNIEnv *env, jobject thisObj) {
return Info.InterpupillaryDistance;
}
JNIEXPORT jfloatArray JNICALL Java_oculusvr_input_OculusRift_getDistortionK
(JNIEnv *env, jobject thisObj) {
jfloat* distortion = Info.DistortionK;
jfloatArray result;
result = env->NewFloatArray(6);
if (result == NULL) {
return NULL; /* out of memory error thrown */
}
env->SetFloatArrayRegion(result, 0, 6, distortion);
return result;
}
JNIEXPORT jint JNICALL Java_oculusvr_input_OculusRift_getDesktopX
(JNIEnv *env, jobject thisObj) {
return Info.DesktopX;
}
JNIEXPORT jint JNICALL Java_oculusvr_input_OculusRift_getDesktopY
(JNIEnv *env, jobject thisObj) {
return Info.DesktopY;
}
JNIEXPORT jstring JNICALL Java_oculusvr_input_OculusRift_getDisplayDeviceName
(JNIEnv *env, jobject thisObj) {
char *name = Info.DisplayDeviceName;
jstring result = env->NewStringUTF(name);
return result;
}
JNIEXPORT jlong JNICALL Java_oculusvr_input_OculusRift_getDisplayId
(JNIEnv *env, jobject thisObj) {
return Info.DisplayId;
}
</code></pre>
<br />
Edit: Update to the code. Formalized it a bit betterRickardhttp://www.blogger.com/profile/17954757065272982081noreply@blogger.com0tag:blogger.com,1999:blog-6458325712473710372.post-16948871961612279592012-09-15T00:49:00.003-07:002012-09-15T00:49:40.272-07:00Through the last couple of years, i've posted on various social networks about projects that blend gaming-like activities, or at least interactivity with real science projects. It's a subject that has grown together with crowdsourcing, and i find it greatly fascinating, that i can help scientists to new discoveries as a layman.<br />
Most of these projects come down to machine learning, where you help identify positives and negatives in a data set to help the algorithm, or simply to guide scientists to interesting areas.<br />
It has the same kind of appeal as the folding@ projects, where you lend out your cpu to science. But instead, here you lend out what makes humans so great, your mind and capability for pattern recognition.<br />
<br />
It seems that a lot of the projects i've previously tried out are now gathered under one roof; https://www.zooniverse.org/<br />
<br />
I've tried out a few of these projects, helping the Kepler telescope by looking for possible planets orbiting stars in Planet Hunters, and looking for green bubbles (possible star forming locations) for the Milky Way Project.<br />
<br />
An interesting side note is in several of these projects, you can download the raw data for yourself, in case you would like to experiement with your own machine learning algorithms.Rickardhttp://www.blogger.com/profile/17954757065272982081noreply@blogger.com0tag:blogger.com,1999:blog-6458325712473710372.post-5852798996982809402012-06-07T11:14:00.000-07:002012-06-07T11:14:03.138-07:00A free course mealI received an email yesterday, from <a href="http://www.udacity.com/" target="_blank">Udacity</a>, saying they're launching 5 new online courses. I took one of their courses this spring ("CS#373 Programming a Robotic Car"), and I think they're an excellent alternative if you're looking to broaden your knowledge (for free) and get a basic understanding on new topics. All it costs is your time (which is precious enough, i know!).<br />
The new courses are: "Intro to Physics", "Intro to Statistics", "Algorithms", "Logic and Discrete Mathematics" and "Software Testing".<br />
<br />
While I'm at it, I should mention a few other (free) online educational organizations, which I have personal experience from:<br />
<br />
<a href="http://www.coursera.org/" target="_blank">Coursera</a><br />
I took their Machine Language course this winter, which was then just a prototype. Taught by Stanford professor Andrew Ng, it was a great experience, that gave me a lot of insight into this, for me, new area.<br />
<br />
Coursera seems to have a wider span of science topics, whereas Udacity seems to focus more on software development.<br />
<br />
I feel one can't mention online education, without also bringing up <a href="http://www.khanacademy.org/" target="_blank">Khan Academy</a>, the institution that pioneered it all, and also has gamified the experience the most. It presents (mostly) mathematical topics in a very personal and charismatic way, with ways to practice them for those who want to. A great way to freshen up your linear algebra for the other courses, perhaps?<br />
<br />Rickardhttp://www.blogger.com/profile/17954757065272982081noreply@blogger.com0tag:blogger.com,1999:blog-6458325712473710372.post-82359773107798333242012-06-02T09:12:00.000-07:002012-06-02T09:12:05.209-07:00Shi-Tomasi corner detection on AndroidThe following tutorial descibes how to implement a real time Shi Tomasi Corner Detection application in an Android environment using <a href="http://opencv.willowgarage.com/">Open CV</a>.<br />It's aimed at those new to either Open CV, or Android development, and was created as a way (for me, as a Java and Android developer) to get into the world of Open CV.<br /><br /><b>Why Corner Detection?</b><br />Corner detection is a base stepping stone, used in many computer vision applications, when recognizing features in images. <br /><br /><a href="http://en.wikipedia.org/wiki/Corner_detection">http://en.wikipedia.org/wiki/Corner_detection</a><br /><br />In this case, it's a good first glimpse at Open CV, if you're new to it, since it requires little implementation. It's also good if you're familiar with Open CV, but new to android development, as it is a relatively simple android application as well.<br /><br />I'd recommend you to familiarize yourself with the Android examples provided by Open CV, since you will probably recognize the code better, then. <a href="http://code.opencv.org/projects/opencv/wiki/OpenCV4Android">http://code.opencv.org/projects/opencv/wiki/OpenCV4Android</a><br /><br /><b>Basics:</b><br />The application structure is based on tutorial-2-opencvcamera Open CV Android example.<br />The actual implementation is based on this C++ tutorial:<br /><br /><a href="http://opencv.itseez.com/doc/tutorials/features2d/trackingmotion/good_features_to_track/good_features_to_track.html#good-features-to-track">http://opencv.itseez.com/doc/tutorials/features2d/trackingmotion/good_features_to_track/good_features_to_track.html#good-features-to-track</a><br />It is, however, uncommented. I'll try to explain each step, as we go.<br /><br /><b>CameraBaseActivity.java</b><br />This class is more or less identical with the one in the tutorial. If you're familiar with android activities, you can jump to the next class.<div style="margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">public</span></span></span></span><span style="font-size: x-small;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">class</span></span></span></span><span style="font-size: x-small;">
</span><span style="font-family: Courier New,monospace;"><span style="font-size: x-small;">CameraBase</span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Activity</span></span></span><span style="font-size: x-small;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">extends</span></span></span></span><span style="font-size: x-small;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Activity</span></span></span><span style="font-size: x-small;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">private</span></span></span></span><span style="font-size: x-small;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">static</span></span></span></span><span style="font-size: x-small;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">final</span></span></span></span><span style="font-size: x-small;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">String</span></span></span><span style="font-size: x-small;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">TAG</span></span></span><span style="font-size: x-small;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="font-size: x-small;">
</span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">"Sample::Activity"</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">;</span></span></span></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">private</span></span></span></span><span style="font-size: x-small;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">CvViewBase</span></span></span><span style="font-size: x-small;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mView;</span></span></span></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">public</span></span></span></span><span style="font-size: x-small;">
</span><span style="font-family: Courier New,monospace;"><span style="font-size: x-small;">CameraBase</span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Activity()</span></span></span><span style="font-size: x-small;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Log.i(TAG,</span></span></span><span style="font-size: x-small;">
</span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">"Instantiated
new "</span></span></span><span style="font-size: x-small;"> </span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">+</span></span></span><span style="font-size: x-small;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">this</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">.getClass());</span></span></span></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">@Override</span></span></span></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">public</span></span></span></span><span style="font-size: x-small;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">void</span></span></span></span><span style="font-size: x-small;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">onCreate(Bundle</span></span></span><span style="font-size: x-small;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">savedInstanceState)</span></span></span><span style="font-size: x-small;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Log.i(TAG,</span></span></span><span style="font-size: x-small;">
</span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">"onCreate"</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">);</span></span></span></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">super</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">.onCreate(savedInstanceState);</span></span></span></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">requestWindowFeature(Window.FEATURE</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">NO</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">TITLE);</span></span></span></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">getWindow().addFlags(WindowManager.LayoutParams.FLAG</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_F</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">ULLSCREEN</span></span></span><span style="font-size: x-small;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">|</span></span></span><span style="font-size: x-small;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">WindowManager.LayoutParams.FLAG</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">KEEP</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">SCREEN</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">ON);</span></span></span></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<span style="color: black;">
<span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mView = new
ShiTomasiView(this);</span></span></span></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<span style="color: black;">
<span style="font-family: Courier New,serif;"><span style="font-size: x-small;">setContentView(mView);</span></span></span></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6e6; margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<br />Nothing too surprising in this little class. The onCreate() method sets a few window settings, like removing the title bar, and making sure the screen stays on even if it's not touched for a certain amount of time.<br />It also creates an instance of our View, which will do most of the work.<br />
<br />ShiTomasiView is an extension of the CvViewBase class. Again, CvViewBase is more or less identical with the example class, so ifyou're familiar with that, you can skip this section.<br /><br /><b>CvViewBase.java</b><br />
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">public</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">abstract</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">class</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">CvViewBase</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">extends</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">SurfaceView</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">implements</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">SurfaceHolder.Callback,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Runnable</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">private</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">static</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">final</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">String</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">TAG</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">"Sample::SurfaceView"</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">private</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">SurfaceHolder</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mHolder;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">private</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">VideoCapture</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mCamera;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">public</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">CvViewBase(Context</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">context)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">super</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(context);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mHolder</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">getHolder();</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mHolder.addCallback(</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">this</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Log.i(TAG,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">"Instantiated
new "</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">+</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">this</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">.getClass());</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<br />
Here we see the first reference to Open CV, a VideoCapture object. Properly named, it's used to grab the image from the device's camera. We also see that the class is a SurfaceView, which gives us something to draw on, and a Runnable. <br /><br />
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">public</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">void</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">surfaceCreated(SurfaceHolder</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">holder)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Log.i(TAG,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">"surfaceCreated"</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mCamera</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">new</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">VideoCapture(Highgui.CV</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">CAP</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">ANDROID);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">if</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(mCamera.isOpened())</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">new</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Thread(</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">this</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">)).start();</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">else</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mCamera.release();</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mCamera</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">null</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Log.e(TAG,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">"Failed
to open native camera"</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<br />
When the surface is first created, we instantiate a new VideoCapture, and let it know what kind of device it is (we're working with Android, here).<br /><br />If all is well, we start the thread (this is a Runnable).<br /><br />
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">public</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">void</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">surfaceChanged(SurfaceHolder</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">holder,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">int</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">format,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">int</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">width,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">int</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">height)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Log.i(TAG,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">"surfaceCreated"</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">synchronized</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">this</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">if</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(mCamera</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">!=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">null</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">&&</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mCamera.isOpened())</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Log.i(TAG,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">"before
mCamera.getSupportedPreviewSizes()"</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">List<Size></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">sizes</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mCamera.getSupportedPreviewSizes();</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Log.i(TAG,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">"after
mCamera.getSupportedPreviewSizes()"</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">int</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mFrameWidth</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">width;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">int</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mFrameHeight</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">height;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99ccff;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">//
selecting optimal camera preview size</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">double</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">minDiff</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">Double</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">.MAX</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">VALUE;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">for</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(Size</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">size</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">:</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">sizes)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">if</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(Math.abs(size.height</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">-</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">height)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;"><</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">minDiff)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mFrameWidth</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">int</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">size.width;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mFrameHeight</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">int</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">size.height;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">minDiff</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Math.abs(size.height</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">-</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">height);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mCamera.set(Highgui.CV</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">CAP</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">PROP</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_F</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">RAME</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">WIDTH,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mFrameWidth);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mCamera.set(Highgui.CV</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">CAP</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">PROP</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_F</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">RAME</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">HEIGHT,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mFrameHeight);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<br />Every time the surface changes (like, when you flip from portrait to landscape) this method will be called. It compares the dimensions of the old and new views and adjust to the new conditions.<br /><br /><div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">public</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">void</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">surfaceDestroyed(SurfaceHolder</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">holder)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Log.i(TAG,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">"surfaceDestroyed"</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">if</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(mCamera</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">!=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">null</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">synchronized</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">this</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mCamera.release();</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mCamera</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">null</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<br />
When the surface is no longer used, this method releases the VideoCapture resources.That was the basic surface handling methods. Now we come to the parts that actually do something.<br /><br />
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">protected</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">abstract</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Bitmap</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">processFrame(VideoCapture</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">capture);</span></span></span></div>
<br />
This abstract method is what does the application specific logic. It is called from the run() method, below.<br /><br />
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">public</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">void</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">run()</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Log.i(TAG,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">"Starting
processing thread"</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">while</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">true</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Bitmap</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">bmp</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">null</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">synchronized</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">this</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">if</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(mCamera</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">==</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">null</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">)</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">break</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">if</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(!mCamera.grab())</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Log.e(TAG,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">"mCamera.grab()
failed"</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">break</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">bmp</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">processFrame(mCamera);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">if</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(bmp</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">!=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">null</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Canvas</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">canvas</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mHolder.lockCanvas();</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">if</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(canvas</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">!=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">null</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">canvas.drawBitmap(bmp,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(canvas.getWidth()</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">-</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">bmp.getWidth())</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">/
2, (canvas.getHeight() - bmp.getHeight()) / 2, </span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">null</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">mHolder.unlockCanvasAndPost(canvas);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: blue;"> </span><span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">bmp.recycle();</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: blue;"> </span><span style="color: black;"> </span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Log.i(TAG,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">"Finishing
processing thread"</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<br />
The main loop of the application. The Bitmap bmp is where we will draw the results of the processFrame() method. So, this is what the run() method does in general:<br /><br />
Create a new Bitmap.<br /><br />
Grab the image from the camera (this is an important step, which must be called prior to retrieve() )<br /><br />
Call processFrame(), which will do the manipulations.<br /><br />
Draw whatever comes back (if anything).<br /><br />
Repeat.<br /><br />As you might have noticed, so far it doesn't do anything. In fact, it doesn't even work since it calls an abstract method that isn't implemented anywhere.<br />This brings us to the next class, ShiTomasiView.java. It's based on Sample2View.java in the example.<br /><br /><b>ShiTomasiView.java:</b><br />
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">public</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">class</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
ShiTomasiView </span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">extends</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
CvViewBase {</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">private</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
Mat sceneColor;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">private</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
Mat sceneGrayScale;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">private</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">final</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">static</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">double</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
qualityLevel = </span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">0.35</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">private</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">final</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">static</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">double</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
minDistance = </span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">10</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">private</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">final</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">static</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">int</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
blockSize = </span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">8</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">private</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">final</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">static</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">boolean</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
useHarrisDetector = </span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">false</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">private</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">final</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">double</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
k = </span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">0.0</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">private</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">final</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">static</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">int</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
maxCorners = </span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">100</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">private</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">final</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">static</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
Scalar circleColor = </span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">new</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
Scalar(</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">0</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">,
</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">255</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">,
</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">0</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">public</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">
ShiThomasiView(Context context) {</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">super</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(context);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
<span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<br />
First of all we declare a bunch of variables. Mat is Open CV's Matrix class. For starters, we're going to use 2 Mat's to store the camera image in, one in color (RGB), and one black and white.<br /><br />
The rest are values needed for the corner detection algorithm. You will find that you most likely have to tweak them to suit your needs. A good follow up excercise could be to let the application find out the best values by itself. Let's ignore them for now and i'll explain them when we need them.<br /><br />
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">public</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">void</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">surfaceChanged(SurfaceHolder</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">holder,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">int</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">format,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">int</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">width,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">int</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">height){</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">super</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">.surfaceChanged(</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">holder,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">format,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">width,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">height);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">synchronized</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">this</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">sceneGrayScale</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">new</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Mat();</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">sceneColor</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">new</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Mat();</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<br />
When the surface is created, we instantiate the two Mat's we're going to use. Don't forget to call super.<br /><br />
Now we come to the actual image processing method. Let's break it up a bit.<br /><br />
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">protected</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Bitmap</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">processFrame(VideoCapture</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">capture)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: blue;"> </span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">capture.retrieve(sceneColor,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Highgui.CV</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">CAP</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">ANDROID</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">COLOR</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_F</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">RAME</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">RGB);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Imgproc.cvtColor(sceneColor,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">sceneGrayScale,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Imgproc.COLOR</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">RGB2GRAY);</span></span></span></div>
<br />Remember how we called capture.grab() in the previous class? Now we will retrieve that frame from the camera, and put it in the sceneColor matrix.<br /><br />We then use cvtColor to convert it to grayscale with the COLOR_RGB2GRAY constant, and thus put it in the sceneGrayScale Mat.<br /><br />Why convert the image to grayscale?<br />In computer vision, it's common to do this. Afaik, for two reasons; <br />Features become more easily distinguishable since the contrast becomes clearer. <br />It improves performance and memory usage (a pixel is stored in 1 byte instead of 3) <br /><br /><div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">MatOfPoint</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">corners</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">new</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">MatOfPoint();</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Imgproc.goodFeaturesToTrack(sceneGrayScale,</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">corners,</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">maxCorners,</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">qualityLevel,</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">minDistance,</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">new</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Mat(),</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">blockSize,</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">useHarrisDetector,</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">k);</span></span></span></div>
<br />
Now it's time to put the libraries to good use. The goodFeaturesToTrack does most of the work for us, and gives us back a list of corners (in the form of a 1D Mat). To do this, we need to supply it with some values. So let's go through the parameters.<br /><br />
sceneGrayScale is our image we want to detect corners in.<br />corners is our list of corners found by the algorithm.<br />maxCorners is the maximum number of corners we want it to return.<br />qualityLevel is the minimum ”quality level” of the results found for the result to be considered a corner.<br />minDistance is the minimum distance in pixels required from one corner to the next.<br />In the next one we can supply a mask Mat in case we want to focus on a certain area of the image.<br />blockSize is in how big an area in pixels, the algorithm will use to define corners.<br />The next boolean is whether we're going to use Harris Corner Detection or not. In this example we aren't.<br />We can ignore the k value, since it's only used in Harris Corner Detection.<br /><br />
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Bitmap</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">bmp</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Bitmap.createBitmap(sceneGrayScale.cols(),</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">sceneGrayScale.rows(),</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Bitmap.Config.RGB</span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">_565</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span>
</div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Point[]</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">points</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">corners.toArray();</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">for</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(Point</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">p</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">:</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">points)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Core.circle(sceneColor,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">p,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">5</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">circleColor);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span>
</div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">try</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Utils.matToBitmap(sceneColor,</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">bmp);</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">catch</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(Exception</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">e)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">Log.e(</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">this</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">.getClass().getSimpleName(),</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: blue;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">"Exception
thrown: "</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">+</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">e.getMessage());</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">bmp.recycle();</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">return</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">bmp;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<br />We're now ready to draw our results and create a new bitmap, defining it as as an RGB image(no alpha).<br /><br />To access the Point elements we convert it to an array.<br /><br />Open CV has a bunch of image manipulation methods built in, which we're going to use. An option would be to draw everything on an Android Canvas.<br /><br />Circle creates a ring on the supplied Mat, with a radius (5 on this occasion), and a color (green), which we defined as static in the beginning of this class.<br /><br />matToBitmap converts the Mat to a Bitmap (obviously).<br /><br />The bitmap is returned to the run() method in the CvViewBase, which draw it unto the Canvas.<br /><br />That's it! (Almost).<br /><br /><div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">public</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">void</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">run()</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">super</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">.run();</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">synchronized</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(</span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">this</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99ccff;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">//
Explicitly deallocate Mats</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">if</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(sceneColor</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">!=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">null</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">sceneColor.release();</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">if</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">(sceneGrayScale</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">!=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">null</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">)</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">{</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">sceneGrayScale.release();</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<br /></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">sceneColor</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">null</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">sceneGrayScale</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">=</span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-small;">
</span></span></span></span><span style="color: #99284c;"><span style="font-family: Courier New,serif;"><span lang="zxx"><span style="font-size: x-small;">null</span></span></span></span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">;</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<div style="background: #e6e6ff; margin-bottom: 0cm;">
<span style="color: black;">
</span><span style="color: black;"><span style="font-family: Courier New,serif;"><span style="font-size: x-small;">}</span></span></span></div>
<br />
The class also overrides the run() method, and deallocates the resources in our materials (as per the example).<br /><br />
Congratulations! You now have an application that detects interest points in real time.<br /><br />Stay tuned for more stuff.Rickardhttp://www.blogger.com/profile/17954757065272982081noreply@blogger.com7