Created
October 30, 2014 16:41
-
-
Save hecomi/a32489ade372f346e8b7 to your computer and use it in GitHub Desktop.
Light weight leap image retriever
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************************************************************\ | |
* Copyright (C) Leap Motion, Inc. 2011-2014. * | |
* Leap Motion proprietary. Licensed under Apache 2.0 * | |
* Available at http://www.apache.org/licenses/LICENSE-2.0.html * | |
\******************************************************************************/ | |
using UnityEngine; | |
using System.Collections; | |
using Leap; | |
// To use the LeapImageRetriever you must be on version 2.1+ | |
// and enable "Allow Images" in the Leap Motion settings. | |
public class LeapImageRetriever : MonoBehaviour | |
{ | |
public const string NORMAL_SHADER = "LeapMotion/LeapDistorted"; | |
public const string UNDISTORT_SHADER = "LeapMotion/LeapUndistorted"; | |
public const int DEFAULT_TEXTURE_WIDTH = 640; | |
public const int DEFAULT_TEXTURE_HEIGHT = 240; | |
public const int DEFAULT_DISTORTION_WIDTH = 64; | |
public const int DEFAULT_DISTORTION_HEIGHT = 64; | |
public const int IMAGE_WARNING_WAIT = 10; | |
public int imageIndex = 0; | |
public Color imageColor = Color.white; | |
public float gammaCorrection = 1.0f; | |
public bool undistortImage = true; | |
public bool blackIsTransparent = true; | |
protected Controller leap_controller_; | |
// Main texture. | |
protected Texture2D main_texture_; | |
protected Color32[] image_pixels_; | |
protected byte[] image_data_; | |
protected int image_misses_ = 0; | |
// Distortion textures. | |
protected Texture2D distortionX_; | |
protected Texture2D distortionY_; | |
protected Color32[] dist_pixelsX_; | |
protected Color32[] dist_pixelsY_; | |
protected float[] distortion_data_; | |
protected bool isDistortionImageCreated_ = false; | |
protected void SetMainTextureDimensions(int width, int height) | |
{ | |
int num_pixels = width * height; | |
main_texture_ = new Texture2D(width, height, TextureFormat.Alpha8, false); | |
main_texture_.wrapMode = TextureWrapMode.Clamp; | |
image_pixels_ = new Color32[num_pixels]; | |
} | |
protected void SetDistortionDimensions(int width, int height) | |
{ | |
int num_pixels = width * height; | |
distortionX_ = new Texture2D(width, height, TextureFormat.RGBA32, false); | |
distortionY_ = new Texture2D(width, height, TextureFormat.RGBA32, false); | |
distortionX_.wrapMode = TextureWrapMode.Clamp; | |
distortionY_.wrapMode = TextureWrapMode.Clamp; | |
dist_pixelsX_ = new Color32[num_pixels]; | |
dist_pixelsY_ = new Color32[num_pixels]; | |
} | |
void Start() | |
{ | |
leap_controller_ = new Controller(); | |
leap_controller_.SetPolicyFlags(Controller.PolicyFlag.POLICY_IMAGES); | |
SetMainTextureDimensions(DEFAULT_TEXTURE_WIDTH, DEFAULT_TEXTURE_HEIGHT); | |
SetDistortionDimensions(DEFAULT_DISTORTION_WIDTH, DEFAULT_DISTORTION_HEIGHT); | |
renderer.material = new Material(Shader.Find(UNDISTORT_SHADER)); | |
} | |
void Update() | |
{ | |
Frame frame = leap_controller_.Frame(); | |
if (frame.Images.Count == 0) { | |
image_misses_++; | |
if (image_misses_ == IMAGE_WARNING_WAIT) { | |
Debug.LogWarning("Can't find any images. " + | |
"Make sure you enabled 'Allow Images' in the Leap Motion Settings, " + | |
"you are on tracking version 2.1+ and " + | |
"your Leap Motion device is plugged in."); | |
} | |
return; | |
} | |
// Check main texture dimensions. | |
Image image = frame.Images[imageIndex]; | |
int image_width = image.Width; | |
int image_height = image.Height; | |
if (image_width == 0 || image_height == 0) { | |
Debug.LogWarning("No data in the image texture."); | |
return; | |
} | |
if (image_width != main_texture_.width || image_height != main_texture_.height) | |
SetMainTextureDimensions(image_width, image_height); | |
// Check distortion texture dimensions. | |
// Divide by two 2 because there are floats per pixel. | |
int distortion_width = image.DistortionWidth / 2; | |
int distortion_height = image.DistortionHeight; | |
if (distortion_width == 0 || distortion_height == 0) { | |
Debug.LogWarning("No data in the distortion texture."); | |
return; | |
} | |
if (distortion_width != distortionX_.width || distortion_height != distortionX_.height) | |
SetDistortionDimensions(distortion_width, distortion_height); | |
// Load image texture data. | |
image_data_ = image.Data; | |
distortion_data_ = image.Distortion; | |
LoadMainTexture(); | |
ApplyDataToTextures(); | |
renderer.material.mainTexture = main_texture_; | |
renderer.material.SetColor("_Color", imageColor); | |
renderer.material.SetFloat("_GammaCorrection", gammaCorrection); | |
renderer.material.SetInt("_BlackIsTransparent", blackIsTransparent ? 1 : 0); | |
if (!isDistortionImageCreated_) { | |
EncodeDistortion(); | |
ApplyDataToDistTextures(); | |
renderer.material.SetTexture("_DistortX", distortionX_); | |
renderer.material.SetTexture("_DistortY", distortionY_); | |
renderer.material.SetFloat("_RayOffsetX", image.RayOffsetX); | |
renderer.material.SetFloat("_RayOffsetY", image.RayOffsetY); | |
renderer.material.SetFloat("_RayScaleX", image.RayScaleX); | |
renderer.material.SetFloat("_RayScaleY", image.RayScaleY); | |
isDistortionImageCreated_ = true; | |
} | |
} | |
protected void LoadMainTexture() | |
{ | |
int num_pixels = main_texture_.width * main_texture_.height; | |
for (int i = 0; i < num_pixels; ++i) | |
image_pixels_[i].a = image_data_[i]; | |
} | |
// Encodes the float distortion texture as RGBA values to transfer the data to the shader. | |
protected void EncodeDistortion() | |
{ | |
// Move distortion data to distortion x and y textures. | |
int num_distortion_floats = 2 * distortionX_.width * distortionX_.height; | |
for (int i = 0; i < num_distortion_floats; ++i) { | |
float dval = distortion_data_[i]; | |
// The distortion range is -0.6 to +1.7. Normalize to range [0..1). | |
dval = (dval + 0.6f) / 2.3f; | |
if (dval > 1.0f || dval < 0.0f) { | |
Debug.Log("WARNING: got a distortion value outside my encoded range at pixel " + | |
i + ": " + distortion_data_[i]); | |
} | |
// Encode the float as RGBA. | |
float enc_x = dval; | |
float enc_y = dval * 255.0f; | |
float enc_z = 65025.0f * dval; | |
float enc_w = 160581375.0f * dval; | |
enc_x = enc_x - Mathf.Floor(enc_x); | |
enc_y = enc_y - Mathf.Floor(enc_y); | |
enc_z = enc_z - Mathf.Floor(enc_z); | |
enc_w = enc_w - Mathf.Floor(enc_w); | |
enc_x -= 1.0f / 255.0f * enc_y; | |
enc_y -= 1.0f / 255.0f * enc_z; | |
enc_z -= 1.0f / 255.0f * enc_w; | |
int index = i >> 1; | |
if (i % 2 == 0) { | |
dist_pixelsX_[index].r = (byte) (256 * enc_x); | |
dist_pixelsX_[index].g = (byte) (256 * enc_y); | |
dist_pixelsX_[index].b = (byte) (256 * enc_z); | |
dist_pixelsX_[index].a = (byte) (256 * enc_w); | |
} else { | |
dist_pixelsY_[index].r = (byte) (256 * enc_x); | |
dist_pixelsY_[index].g = (byte) (256 * enc_y); | |
dist_pixelsY_[index].b = (byte) (256 * enc_z); | |
dist_pixelsY_[index].a = (byte) (256 * enc_w); | |
} | |
} | |
} | |
protected void ApplyDataToTextures() | |
{ | |
main_texture_.SetPixels32(image_pixels_); | |
main_texture_.Apply(); | |
} | |
protected void ApplyDataToDistTextures() | |
{ | |
distortionX_.SetPixels32(dist_pixelsX_); | |
distortionX_.Apply(); | |
distortionY_.SetPixels32(dist_pixelsY_); | |
distortionY_.Apply(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment