
บทเรียน Javascript กับของเล่นใหม่ Leap Motion สำหรับ Detect มือและนิ้วของเราผ่านอุปกรณ์แสกนแล้วทำการ Rigged กระดูกมือเราให้ใช้งานร่วมกับ โปรแกรมได้
ก่อนอื่นที่จะทำอะไรกับบทความนี้ได้นั้น คุณต้องมีเจ้าเครื่อง Leap Motion มาก่อน สามารถสั่งซื้อผ่านอินเทอร์เน็ตได้ ในราคา 79.99$ (http://store-us.leapmotion.com/) ไม่แพงสำหรับการเรียนรู้อะไรใหม่ๆ


ได้ของแล้วก็ทำการติดตั้งซะ

เมื่อได้ของมาแล้วก็ให้ไปดาวน์โหลดตัว Driver และ SDK ซะเลยสำหรับนักพัฒนา

ทำการติดตั้งแล้วก็เปิด Virtualize ทดสอบมันซะหน่อย


ทีนี้ก็มาพัฒนาโปรแกรมร่วมกับมันซะหน่อย อันที่จริง มันมีเกมมาให้เยอะแยะเลยนะให้เราเล่น แต่เราจะมองข้ามไป ไปพัฒนากันจริงๆ จังๆ ซึ่งรูปแบบการพัฒนามีให้เลือกอยู่มากมาย ผมจึงเลือกมาแค่ 2 แพลตฟอร์มคือ C# (Unity) กับ Javascript
เรามาเริ่ม Essential Lesson ด้วย Javascript ก่อน ตัว SDK มันก็มีให้แกะแหละครับ แต่การรับรู้ของคนเรามีไม่เท่ากันดังนั้นก็เลย ย่อยมาให้
รูปแบบ Leap Motion ตัวนี้ก็คือการ Detect จับว่ามือเรานั้นเป็นข้างไหน และมีสถานะ กำมือ หรือ แบมืออยู่
เขียน HTML ขึ้นมาก่อนเลยครับ ไฟล์ index.html
<!DOCTYPE html> <!-- DAYDEV CO., LTD. CASE STUDY--> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Leap Motion JS Hand Detect</title> <!-- SDK--> <!-- SDK--> </head> <body> <h1>Console</h1> <div id="main"> <div id="handData"></div> <div style="clear:both;"></div> </div> </body> </html>
ตัว Leap Motion จะมี SDK แบบ Online ให้เราเรียกใช้ครับ แทรก คำสั่งนี้ลงใน <!–SDK–> ได้เลย
<script src="http://js.leapmotion.com/leap-0.6.3.min.js"></script>
ให้เราทำการเขียน ฟังก์ชัน Javascript ขึ้นมาใหม่บน <head> ดังนี้ครับ
// Store frame for motion functions
var previousFrame = null;
var paused = false;
var pauseOnGesture = false;
// Setup Leap loop with frame callback function
var controllerOptions = {enableGestures: true};
เป็นการตรวจสอบการ Detect Gesture ของการเคลื่อนไหวผ่าน Censor ของ Leap Motion ครับ ตามด้วย
Leap.loop(controllerOptions, function(frame) {
if (paused) {
return; // Skip this update
}
// Display Hand object data
var handOutput = document.getElementById("handData");
var handString = "";
if (frame.hands.length > 0) {
for (var i = 0; i < frame.hands.length; i++) {
var hand = frame.hands[i];
handString += "<div style='width:400px; float:left; padding:5px'>";
handString += "ID มือ: " + hand.id + "<br />";
handString += "ข้างที่ใช้: " + hand.type + "<br />";
handString += "ทิศทาง: " + vectorToString(hand.direction, 2) + "<br />";
handString += "กำมือ: " + hand.grabStrength + "<br />";
// IDs of pointables associated with this hand
if (hand.pointables.length > 0) {
var fingerIds = [];
for (var j = 0; j < hand.pointables.length; j++) {
var pointable = hand.pointables[j];
fingerIds.push(pointable.id);
}
if (fingerIds.length > 0) {
handString += "ID มือ และ นิ้ว: " + fingerIds.join(", ") + "<br />";
}
}
handString += "</div>";
}
}
else {
handString += "No hands detect";
}
handOutput.innerHTML = handString;
previousFrame = frame;
})
function vectorToString(vector, digits) {
if (typeof digits === "undefined") {
digits = 1;
}
return "(" + vector[0].toFixed(digits) + ", "
+ vector[1].toFixed(digits) + ", "
+ vector[2].toFixed(digits) + ")";
}
โดย Parameter ที่จำเป็นจะอยู่ส่วนนี้ครับ
var hand = frame.hands[i];
handString += "<div style='width:400px; float:left; padding:5px'>";
handString += "ID มือ: " + hand.id + "<br />";
handString += "ข้างที่ใช้: " + hand.type + "<br />";
handString += "ทิศทาง: " + vectorToString(hand.direction, 2) + "<br />";
handString += "กำมือ: " + hand.grabStrength + "<br />";
เราจะมี hand.id ไว้จับว่ามือที่ปรากฏบน censor ณ ขณะนั้นคือมือของใคร เช่น นาย A มี ID คือ 123 แล้วยกอีกมือมาเป็น 124 แต่จู่ๆ มีนาย B เดินมายกอีกข้างสักข้างมันจะนับเป็น 125 ซึ่งจะไม่มีการเรียก Detect แต่เมื่อนาย A ยกมือ 124 ลง มันจะมองว่า ระบบมีมือ 2 ข้างคือ 123 และ 125 นั่นก็คือมือคนละข้างของ A และ B
ตามด้วย hand.type จะมีการ Rigged กระดูกมือเราเสร็จสรรพ และบอกได้เลยว่าเป็นมือ ข้าง ซ้าย หรือ ขวา โดย return ค่าเป็น left, right ครับ
hand.grabStrength เป็นสถานะของการ แบมือ และ กำมือ ถ้าแบมือจะมีค่าเป็น 0 ไปเรื่อย แต่ถ้ามีสถานะกำมือเมื่อไหร มันจะกลายเป็น 1 ไว้เทียบค่าแบบ Parameter ร่วมกับ Boolean ได้
ใส่ code ลงไปเลย จะเห็นว่า ภาพรวมของ code เป็นดังนี้
<!DOCTYPE html>
<!-- DAYDEV CO., LTD. CASE STUDY-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Leap Motion JS Hand Detect</title>
<script src="http://js.leapmotion.com/leap-0.6.3.min.js"></script>
<script>
// Store frame for motion functions
var previousFrame = null;
var paused = false;
var pauseOnGesture = false;
// Setup Leap loop with frame callback function
var controllerOptions = {enableGestures: true};
Leap.loop(controllerOptions, function(frame) {
if (paused) {
return; // Skip this update
}
// Display Hand object data
var handOutput = document.getElementById("handData");
var handString = "";
if (frame.hands.length > 0) {
for (var i = 0; i < frame.hands.length; i++) {
var hand = frame.hands[i];
handString += "<div style='width:400px; float:left; padding:5px'>";
handString += "ID มือ: " + hand.id + "<br />";
handString += "ข้างที่ใช้: " + hand.type + "<br />";
handString += "ทิศทาง: " + vectorToString(hand.direction, 2) + "<br />";
handString += "กำมือ: " + hand.grabStrength + "<br />";
// IDs of pointables associated with this hand
if (hand.pointables.length > 0) {
var fingerIds = [];
for (var j = 0; j < hand.pointables.length; j++) {
var pointable = hand.pointables[j];
fingerIds.push(pointable.id);
}
if (fingerIds.length > 0) {
handString += "ID มือ และ นิ้ว: " + fingerIds.join(", ") + "<br />";
}
}
handString += "</div>";
}
}
else {
handString += "No hands detect";
}
handOutput.innerHTML = handString;
previousFrame = frame;
})
function vectorToString(vector, digits) {
if (typeof digits === "undefined") {
digits = 1;
}
return "(" + vector[0].toFixed(digits) + ", "
+ vector[1].toFixed(digits) + ", "
+ vector[2].toFixed(digits) + ")";
}
</script>
</head>
<body>
<h1>Console</h1>
<div id="main">
<div id="handData"></div>
<div style="clear:both;"></div>
</div>
</body>
</html>
มาทดสอบกันหน่อย ผมสร้าง http://localhost/LEAP ขึ้นมาทดสอบ



ถ้าเอามือไปวาง 2 มือ มันก็จะปรากฏค่าออกมาเป็น 2 colums ให้เรารู้ว่า มือแต่ละข้างคือมือไหน ตามด้วย ID มือและนิ้ว มือ ID 168 ถ้านิ้วโป้ง 1680, นิ้วชี้ 1681 เป็นต้น

พอดี รีวิวคนเดียวเลย จับหน้าจอแบบ 2 มือไม่ได้แต่เอาเป็นว่ามันแสดงผลได้ครับ
ยังไง ต่อไปคงจะใช้ต่อยอดกับ Unity (C#) กับเกมที่ต้องใช้มือควบคุมครับ ส่วน Leap Motion เหมาะกับงานประเภทไหน ก็คงบอกตรงๆ ว่า เหมาะกับงาน Event พวก Show Case หรือเกมแนว Mo Cap ครับ




